This commit was generated by cvs2svn to compensate for changes in r564,
authorrobertl <robertl@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Tue, 2 Dec 2003 15:03:21 +0000 (15:03 +0000)
committerrobertl <robertl@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Tue, 2 Dec 2003 15:03:21 +0000 (15:03 +0000)
which included commits to RCS files with non-trunk default branches.

38 files changed:
st2gpx/istorage/istorage LICENCE.txt [new file with mode: 0644]
st2gpx/istorage/istorage-make LICENCE.txt [new file with mode: 0644]
st2gpx/istorage/istorage-make README.txt [new file with mode: 0644]
st2gpx/istorage/istorage-make.cpp [new file with mode: 0644]
st2gpx/libexpat.dll [new file with mode: 0644]
st2gpx/src/Expat license.txt [new file with mode: 0644]
st2gpx/src/ToDo.txt [new file with mode: 0644]
st2gpx/src/annotations.c [new file with mode: 0644]
st2gpx/src/annotations.h [new file with mode: 0644]
st2gpx/src/bugs.txt [new file with mode: 0644]
st2gpx/src/build.txt [new file with mode: 0644]
st2gpx/src/contents.c [new file with mode: 0644]
st2gpx/src/contents.h [new file with mode: 0644]
st2gpx/src/debug.c [new file with mode: 0644]
st2gpx/src/gpx.h [new file with mode: 0644]
st2gpx/src/history.txt [new file with mode: 0644]
st2gpx/src/istorage license.txt [new file with mode: 0644]
st2gpx/src/istorage-make license.txt [new file with mode: 0644]
st2gpx/src/journey.c [new file with mode: 0644]
st2gpx/src/journey.h [new file with mode: 0644]
st2gpx/src/msado15.tlh [new file with mode: 0644]
st2gpx/src/msado15.tli [new file with mode: 0644]
st2gpx/src/nannol.c [new file with mode: 0644]
st2gpx/src/ppinutil.c [new file with mode: 0644]
st2gpx/src/ppinutil.h [new file with mode: 0644]
st2gpx/src/properties.c [new file with mode: 0644]
st2gpx/src/properties.h [new file with mode: 0644]
st2gpx/src/pushpins.cpp
st2gpx/src/pushpins.h
st2gpx/src/readgpx.c [new file with mode: 0644]
st2gpx/src/readmpst.c [new file with mode: 0644]
st2gpx/src/st2gpx license.txt [new file with mode: 0644]
st2gpx/src/st2gpx.c
st2gpx/src/st2gpx.dsp
st2gpx/src/st2gpx.dsw
st2gpx/src/st2gpx.h [new file with mode: 0644]
st2gpx/src/writegpx.c [new file with mode: 0644]
st2gpx/src/writepcx.c [new file with mode: 0644]

diff --git a/st2gpx/istorage/istorage LICENCE.txt b/st2gpx/istorage/istorage LICENCE.txt
new file mode 100644 (file)
index 0000000..fde84df
--- /dev/null
@@ -0,0 +1,24 @@
+Copyright (c) 2001, Pabs (pabs3@zip.to)\r
+All rights reserved.\r
+\r
+Redistribution and use in source and binary forms, with or without\r
+modification, are permitted provided that the following conditions\r
+are met:\r
+\r
+Redistributions of source code must retain the above copyright notice,\r
+this list of conditions and the following disclaimer.\r
+Redistributions in binary form must reproduce the above copyright\r
+notice, this list of conditions and the following disclaimer in the\r
+documentation and/or other materials provided with the distribution.\r
+\r
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\r
+HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\r
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\r
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
diff --git a/st2gpx/istorage/istorage-make LICENCE.txt b/st2gpx/istorage/istorage-make LICENCE.txt
new file mode 100644 (file)
index 0000000..5ee1421
--- /dev/null
@@ -0,0 +1,24 @@
+Copyright (c) 2002, Pabs (pabs3@zip.to)\r
+All rights reserved.\r
+\r
+Redistribution and use in source and binary forms, with or without\r
+modification, are permitted provided that the following conditions\r
+are met:\r
+\r
+Redistributions of source code must retain the above copyright notice,\r
+this list of conditions and the following disclaimer.\r
+Redistributions in binary form must reproduce the above copyright\r
+notice, this list of conditions and the following disclaimer in the\r
+documentation and/or other materials provided with the distribution.\r
+\r
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\r
+HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\r
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\r
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
diff --git a/st2gpx/istorage/istorage-make README.txt b/st2gpx/istorage/istorage-make README.txt
new file mode 100644 (file)
index 0000000..fc0813e
--- /dev/null
@@ -0,0 +1,17 @@
+There are two executables, with just the default output type changed:\r
+\r
+istorage-make.exe\r
+       defaults to making OLE IStorages\r
+       made from the distributed source with MSVC 6\r
+\r
+its-make.exe\r
+       defaults to making compressed ITS ITStorages\r
+       made from modified source with MSVC 6\r
+\r
+Read LICENCE.txt for conditions of distribution and modification.\r
+To use just drag a folder onto the appropriate executable/shortcut.\r
+Don't worry about the warnings saying that the times could not be set.\r
+\r
+Enjoy say i,\r
+Pabs <pabs3@zip.to>\r
+http://zip.to/pabs3/
\ No newline at end of file
diff --git a/st2gpx/istorage/istorage-make.cpp b/st2gpx/istorage/istorage-make.cpp
new file mode 100644 (file)
index 0000000..6e5cc62
--- /dev/null
@@ -0,0 +1,218 @@
+/*Copyright by Pabs (pabs3@zip.to, http://zip.to/pabs3/) Dec 2002*/\r
+\r
+/*Licenced under the BSD sloppyright - nasty little daemons better not use this source & not attribute me*/\r
+\r
+/*Compile notes:\r
+       M$VC: just open this file & press the build button or select build from the\r
+             build menu since this will create a default project that does nicely\r
+       GCC/Cygwin: gcc -mno-cygwin -fvtable-thunks -o istorage-make.exe istorage-make.cpp -lole32 should do the trick\r
+                   if w32api & mingw are set up correctly & the headers are correct\r
+       GCC/Wine: You'll have to figure it out for yourself since I don't yet have\r
+                 access to Linux (Debian) cause I need a new HD + a DVD drive ;-)\r
+*/\r
+\r
+/* Usage:\r
+       -ole\r
+               convert to an OLE compound file (default)\r
+       -its\r
+               convert to an ITS file\r
+       -its -uc\r
+               don't compress (default)\r
+       -its -cd\r
+               compress the data after creation\r
+       -its -cdp\r
+               compress the data and path after creation\r
+*/\r
+\r
+/*TODO:\r
+       think up a proper name\r
+       Add popt/getopt processing\r
+       use libOLE on non-win32 - http://chicago.sf.net\r
+       Implement options for the following\r
+               rename specific files to something the normal filesystem can't handle, like 0x1 characters\r
+               various tar/unzip options\r
+               --help --version\r
+*/\r
+\r
+\r
+#include <windows.h>\r
+#include <ole2.h>\r
+#include <stdio.h>\r
+#include <string.h>\r
+\r
+\r
+//These next few bits are from a sample available from http://www.keyworks.net/code.htm (see http://helpware.net/delphi/index.html for a Delphi sample - need to join a yahoo group first - example 10 is the one to look at)\r
+//This stuff is supposed to be documented in the MSDN, but I only found 1 page that references ITStorage & that is an error codes list\r
+DEFINE_GUID(CLSID_ITStorage, 0x5d02926a, 0x212e, 0x11d0, 0x9d, 0xf9, 0x0, 0xa0, 0xc9, 0x22, 0xe6, 0xec);\r
+DEFINE_GUID(IID_ITStorage, 0x88cc31de, 0x27ab, 0x11d0, 0x9d, 0xf9, 0x0, 0xa0, 0xc9, 0x22, 0xe6, 0xec);\r
+\r
+const GUID CLSID_ITStorage = { 0x5d02926a, 0x212e, 0x11d0, { 0x9d, 0xf9, 0x0, 0xa0, 0xc9, 0x22, 0xe6, 0xec } };\r
+const GUID IID_ITStorage = { 0x88cc31de, 0x27ab, 0x11d0, { 0x9d, 0xf9, 0x0, 0xa0, 0xc9, 0x22, 0xe6, 0xec} };\r
+\r
+typedef struct _ITS_Control_Data\r
+{\r
+       UINT cdwControlData; // Number of DWords to follow.\r
+       UINT adwControlData[1]; // Actually this will be adwControlData[cdwControlData]\r
+} ITS_Control_Data, *PITS_Control_Data;\r
+\r
+typedef enum ECompactionLev {\r
+       COMPACT_DATA = 0,\r
+       COMPACT_DATA_AND_PATH\r
+};\r
+\r
+DECLARE_INTERFACE_(IITStorage, IUnknown)\r
+{\r
+       STDMETHOD(StgCreateDocfile) (const WCHAR* pwcsName, DWORD grfMode, DWORD reserved, IStorage** ppstgOpen) PURE;\r
+       STDMETHOD(StgCreateDocfileOnILockBytes) (ILockBytes * plkbyt, DWORD grfMode, DWORD reserved, IStorage** ppstgOpen) PURE;\r
+       STDMETHOD(StgIsStorageFile) (const WCHAR * pwcsName) PURE;\r
+       STDMETHOD(StgIsStorageILockBytes) (ILockBytes * plkbyt) PURE;\r
+       STDMETHOD(StgOpenStorage)(const WCHAR * pwcsName, IStorage * pstgPriority, DWORD grfMode, SNB snbExclude, DWORD reserved, IStorage ** ppstgOpen) PURE;\r
+       STDMETHOD(StgOpenStorageOnILockBytes)(ILockBytes * plkbyt, IStorage * pStgPriority, DWORD grfMode, SNB snbExclude, DWORD reserved, IStorage ** ppstgOpen) PURE;\r
+       STDMETHOD(StgSetTimes)(WCHAR const* lpszName, FILETIME const* pctime, FILETIME const* patime, FILETIME const* pmtime) PURE;\r
+       STDMETHOD(SetControlData)(PITS_Control_Data pControlData) PURE;\r
+       STDMETHOD(DefaultControlData)(PITS_Control_Data *ppControlData) PURE;\r
+       STDMETHOD(Compact)(const WCHAR* pwcsName, ECompactionLev iLev) PURE;\r
+};\r
+\r
+IITStorage* ITStorage = NULL;\r
+\r
+struct OPTIONS{\r
+       bool its;\r
+       bool compress;\r
+       ECompactionLev compression;\r
+       char indentchar;\r
+       char* ole_appendstring;\r
+       char* its_appendstring;\r
+} options = {false,false,COMPACT_DATA,'\t',".ole",".its"};\r
+\r
+HRESULT r;\r
+\r
+void EnumFolder(char*f,IStorage* is);\r
+\r
+int main(int argc, char *argv[]){\r
+       //Get an instance of the thing to call for creating chms\r
+       CoInitialize(NULL);\r
+       CoCreateInstance(CLSID_ITStorage, NULL, CLSCTX_INPROC_SERVER, IID_ITStorage, (void**)&ITStorage);\r
+       char t[2];DWORD cdl = GetCurrentDirectory(2,t);\r
+       char* current_dir = new char[cdl];\r
+       if(current_dir){\r
+               if(GetCurrentDirectory(cdl,current_dir)){\r
+                       for(int argi=1;argi<argc;argi++){\r
+                               if( strcmp(argv[argi],"-ole") == 0 ){ options.its = false; continue; }\r
+                               else if( strcmp(argv[argi],"-its") == 0 ){ options.its = true; continue; }\r
+                               else if( strcmp(argv[argi],"-uc") == 0 ){ options.compress = false; continue; }\r
+                               else if( strcmp(argv[argi],"-cd") == 0 ){\r
+                                       options.compress = true;\r
+                                       options.compression = COMPACT_DATA;\r
+                                       continue;\r
+                               } else if( strcmp(argv[argi],"-cdp") == 0 ){\r
+                                       options.compress = true;\r
+                                       options.compression = COMPACT_DATA_AND_PATH;\r
+                                       continue;\r
+                               }\r
+               \r
+                               if(SetCurrentDirectory(current_dir)){\r
+                                       if(SetCurrentDirectory(argv[argi])){\r
+                                               if(SetCurrentDirectory("..")){\r
+                                                       unsigned int len = strlen(argv[argi]);\r
+                                                       char* appendstring = options.its ? options.its_appendstring : options.ole_appendstring;\r
+                                                       unsigned int appendstring_len = strlen(appendstring);\r
+                                                       char* file = new char[len+appendstring_len+1];\r
+                                                       if(file){\r
+                                                               strcpy(file,argv[argi]);\r
+                                                               strcpy(&file[len],appendstring);\r
+                       \r
+                                                               DWORD wlen = MultiByteToWideChar(CP_ACP,0,file,len+appendstring_len+1,NULL,0);\r
+                                                               WCHAR* wfile = new WCHAR[wlen+1];\r
+                                                               if(wfile){\r
+                                                                       if(MultiByteToWideChar(CP_ACP,0,file,len+appendstring_len+1,wfile,wlen)){\r
+                                                                               IStorage* is = NULL;\r
+                                                                               if( options.its && ITStorage )\r
+                                                                                       r = ITStorage->StgCreateDocfile( wfile, STGM_CREATE|STGM_WRITE|STGM_SHARE_EXCLUSIVE, 0, &is );\r
+                                                                               else\r
+                                                                                       r = StgCreateDocfile( wfile, STGM_CREATE|STGM_WRITE|STGM_SHARE_EXCLUSIVE, 0, &is );\r
+                       \r
+                                                                               if( r == S_OK || is ){\r
+                                                                                       EnumFolder( argv[argi], is );\r
+                                                                                       is->Release(); is = NULL;\r
+                                                                                       if( options.its && ITStorage && options.compress ){\r
+                                                                                               r = ITStorage->Compact( wfile, options.compression );\r
+                                                                                               if(r!=S_OK) fputs("Could not compress the specified file - Ignoring & continuing\n",stderr);\r
+                                                                                       }\r
+                                                                               } else fputs("Could not create the specified file - Ignoring & continuing\n",stderr);\r
+                                                                       } else fputs("Could not convert the path to Unicode for the Unicode only StgOpenStorage - Ignoring & continuing\n",stderr);\r
+                                                                       delete[]wfile; wfile = NULL;\r
+                                                               } else fputs("Could not alloc memory for the Unicode filename for the Unicode only StgCreateDocfile - Ignoring & continuing",stderr);\r
+                                                               delete[]file; file = NULL;\r
+                                                       } else fputs("Could not alloc memory for the filename - Ignoring & continuing",stderr);\r
+                                               } else fputs("Could not enter (directory) - Ignoring & continuing\n",stderr);\r
+                                       } else fputs("Could not enter (directory) - Ignoring & continuing\n",stderr);\r
+                               } else fputs("Could not reset current directory - Ignoring & continuing\n",stderr);\r
+                       }\r
+               } else fputs("Could not get current directory - Failed\n",stderr);\r
+       } else fputs("Could not allocate memory for current directory - Failed\n",stderr);\r
+       if( ITStorage ) ITStorage->Release();\r
+       CoUninitialize();\r
+       fflush(stderr);\r
+       return 0;\r
+}\r
+\r
+void EnumFolder(char*fo, IStorage* is){\r
+       if(SetCurrentDirectory(fo)){\r
+               HANDLE ff;WIN32_FIND_DATA wfd;\r
+               ff = FindFirstFile("*",&wfd);\r
+               if(ff!=INVALID_HANDLE_VALUE&&ff!=0){\r
+                       do{\r
+                               if( strcmp(wfd.cFileName,".") == 0 || strcmp(wfd.cFileName,"..") == 0 ) continue;\r
+                               DWORD len = strlen(wfd.cFileName)+1;\r
+                               DWORD wlen = MultiByteToWideChar(CP_ACP,0,wfd.cFileName,len,NULL,0);\r
+                               WCHAR* wpath = new WCHAR[len];\r
+                               if(wpath){\r
+                                       if(MultiByteToWideChar(CP_ACP,0,wfd.cFileName,len,wpath,wlen)){\r
+                                               if(wfd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY){\r
+                                                       IStorage* is2 = NULL;\r
+                                                       r = is->CreateStorage(wpath,STGM_WRITE|STGM_SHARE_EXCLUSIVE,0,0,&is2);\r
+                                                       if( r == S_OK && is2 ){\r
+                                                               EnumFolder(wfd.cFileName,is2);\r
+                                                               //if(S_OK!=is2->SetStateBits(wfd.dwFileAttributes)) fputs("Could not set state bits (directory) - Ignoring & continuing\n",stderr);\r
+                                                               is2->Release(); is2 = NULL;\r
+                                                       } else fputs("Could not create (directory) - Ignoring & continuing\n",stderr);\r
+                                               } else {\r
+                                                       IStream* is2 = NULL;\r
+                                                       r = is->CreateStream(wpath,STGM_WRITE|STGM_SHARE_EXCLUSIVE,0,0,&is2);\r
+                                                       if( r == S_OK && is2 ){\r
+                                                               HANDLE f = CreateFile(wfd.cFileName,GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,NULL);\r
+                                                               if(f!=INVALID_HANDLE_VALUE&&f!=0/*Fucking lying MSDN*/){\r
+                                                                       ULARGE_INTEGER fs={wfd.nFileSizeLow,wfd.nFileSizeHigh},i={0};\r
+                                                                       is2->SetSize(fs);\r
+                                                                       BYTE* p;\r
+                                                                       DWORD nobm = (DWORD)fs.QuadPart, nobr, nobw;\r
+                                                                       for(;;){\r
+                                                                               p = new BYTE[nobm]; if(p)break;\r
+                                                                               nobm/=2; if(!nobm)break;\r
+                                                                       }\r
+                                                                       if(p){\r
+                                                                               bool err = false;\r
+                                                                               do{\r
+                                                                                       if(!ReadFile(f,p,nobm,&nobr,NULL)||nobm!=nobr){fputs("Read error (file) - terminating this file\n",stderr);err=true;}//read less than asked and there was an error other than EOF - MSDN says that the compound file implementation of Read returns S_OK if the end of the stream was reached during the read\r
+                                                                                       nobw=0;\r
+                                                                                       r=is2->Write(p,nobr,&nobw);\r
+                                                                                       i.QuadPart+=nobw;\r
+                                                                                       if(r!=S_OK||nobr!=nobw){fputs("Write error (file) - terminating this file\n",stderr);err=true;}\r
+                                                                               } while (i.QuadPart<fs.QuadPart&&!err);\r
+                                                                               delete[]p; p = NULL;\r
+                                                                       } else fputs("Could not allocate even 1 byte of mem for a buffer for transferring files - please free some memory & try again - Ignoring & continuing\n",stderr);\r
+                                                                       CloseHandle(f); f = NULL;\r
+                                                               } else fputs("Could not open (file) - Ignoring & continuing\n",stderr);\r
+                                                               is2->Release(); is2 = NULL;\r
+                                                       } else fputs("Could not create (file) - Ignoring & continuing\n",stderr);\r
+                                               }\r
+                                               if(S_OK!=is->SetElementTimes(wpath,&wfd.ftCreationTime,&wfd.ftLastAccessTime,&wfd.ftLastWriteTime)) fputs("Could not set the creation, last modification or last access time - Ignoring & continuing\n",stderr);\r
+                                       }\r
+                               }\r
+                       } while(FindNextFile(ff,&wfd));\r
+                       FindClose(ff);\r
+               }\r
+               SetCurrentDirectory("..");\r
+       } else fputs("Could not enter (directory) - Ignoring & continuing\n",stderr);\r
+}\r
diff --git a/st2gpx/libexpat.dll b/st2gpx/libexpat.dll
new file mode 100644 (file)
index 0000000..4c925de
Binary files /dev/null and b/st2gpx/libexpat.dll differ
diff --git a/st2gpx/src/Expat license.txt b/st2gpx/src/Expat license.txt
new file mode 100644 (file)
index 0000000..01db7e8
--- /dev/null
@@ -0,0 +1,22 @@
+Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd\r
+                               and Clark Cooper\r
+Copyright (c) 2001, 2002 Expat maintainers.\r
+\r
+Permission is hereby granted, free of charge, to any person obtaining\r
+a copy of this software and associated documentation files (the\r
+"Software"), to deal in the Software without restriction, including\r
+without limitation the rights to use, copy, modify, merge, publish,\r
+distribute, sublicense, and/or sell copies of the Software, and to\r
+permit persons to whom the Software is furnished to do so, subject to\r
+the following conditions:\r
+\r
+The above copyright notice and this permission notice shall be included\r
+in all copies or substantial portions of the Software.\r
+\r
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\r
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\r
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\r
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\r
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
diff --git a/st2gpx/src/ToDo.txt b/st2gpx/src/ToDo.txt
new file mode 100644 (file)
index 0000000..5405585
--- /dev/null
@@ -0,0 +1,29 @@
+To do:\r
+\r
+       \r
+       import/export more data for pushpins, including symbol, set name(use join on read)\r
+       option to show ppin names/info on import\r
+       center and size map on annotations.\r
+\r
+       Get lat & lon for journey route points not matched to pushpins\r
+       Get point info for non-line annotations, e.g. text boxes.\r
+       import route as s&t route (Journey), i.e. not just as a line.\r
+       fix overuse of realloc\r
+       support unicode names (remove str2ascii)\r
+\r
+       different colours for imported routes & tracks\r
+       export lines with arrows as routes?\r
+       put some of the ole properties into gpx file comments\r
+\r
+       clean up main + string names. Just use stfile+path. Debug read other files\r
+       clean up gpx points/ms points/ names ms2latlon etc\r
+       clean up import structures, make like contents import?\r
+\r
+       support drive-time zones in annotations stream?\r
+\r
+Still to test:\r
+* various versions, esp import\r
+* multiple imports\r
+* import to file with existing data\r
+* import to empty file\r
+* meaning of options etc for v4 files\r
diff --git a/st2gpx/src/annotations.c b/st2gpx/src/annotations.c
new file mode 100644 (file)
index 0000000..c3a3f51
--- /dev/null
@@ -0,0 +1,419 @@
+/*\r
+       annotations.c\r
+\r
+       Extract data from MS Streets & Trips .est and Autoroute .axe files in GPX format.\r
+\r
+    Copyright (C) 2003 James Sherring, james_sherring@yahoo.com\r
+\r
+    This program is free software; you can redistribute it and/or modify\r
+    it under the terms of the GNU General Public License as published by\r
+    the Free Software Foundation; either version 2 of the License, or\r
+    (at your option) any later version.\r
+\r
+    This program is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+\r
+    You should have received a copy of the GNU General Public License\r
+    along with this program; if not, write to the Free Software\r
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA\r
+\r
+\r
+       This app depends on istorage & istorage-make from Pabs (pabs3@zip.to)\r
+       and James Clark's Expat xml parser from http://www.libexpat.org/.\r
+\r
+*/\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <malloc.h>\r
+#include <memory.h>\r
+#include <math.h>\r
+#include <string.h>\r
+\r
+#include "gpx.h"\r
+#include "st2gpx.h"\r
+#include "pushpins.h"\r
+\r
+#include "annotations.h"\r
+\r
+// std_anotfile_header[8,9] are variable (number of annotations)\r
+char std_annotfile_header[12]    //  num annots\r
+       = {0x34, 0x12, 0x00, 0x2d, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00};\r
+\r
+char std_annot_linerec_header_v3[LINE_REC_LEN_V3] =\r
+//   type                   annot#1               ,\r
+       {0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // 0x00\r
+//show length,\r
+//   order\r
+//behind roads\r
+        0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x08\r
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x10\r
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x18\r
+//   blue                     2pt\r
+        0x12, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, // 0x20\r
+//                         show line\r
+        0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // 0x28\r
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x30\r
+        0x00};\r
+\r
+char std_annot_linerec_header_v4[LINE_REC_LEN_V4] =\r
+//   type                   annot#1               ,\r
+       {0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // 0x00\r
+\r
+        0x00, 0x00, 0x00, 0x00, \r
+\r
+//show length,\r
+//   order\r
+//behind roads\r
+        0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \r
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \r
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \r
+//   blue                     2pt\r
+        0x12, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, \r
+//                         show line\r
+        0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, \r
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \r
+        0x00};\r
+\r
+//struct parameters {\r
+// Also need to include variable text length + line-points with these\r
+\r
+// These change with file version, so handle in code\r
+int annot_rec_len[4]={57, 868, 124, 868};\r
+//int annot_head_len[4]={57, 48, 48, 48};\r
+\r
+char * annot_type_name[4]={"Line", "Oval", "Textbox", "Circle"};\r
+//} tag_parameters;\r
+\r
+// constants for converting from MS Grid & Precision to latitude and longitude\r
+// double magic1=182.044444444444; // = 2^16/360\r
+// double magic2=0x10000;\r
+\r
+/*\r
+typedef struct annotationbuf\r
+{\r
+       int annot_num;\r
+       int flags;              // bit fields in first byte\r
+       int unkn1;              // normally 0\r
+       int unkn2;              // ? seems to have byte fields\r
+       int text_len;\r
+       // + 2*text_len bytes of text here\r
+       int fill_color; // seems to have byte fields. First byte is fill, other bytes are strange\r
+       int line_color;\r
+       int line_thickness; // 20 times the point-size\r
+       int arrow_type;         // 00=none, 01=left, 02=right, 03=both\r
+       int unkn3;\r
+       int joinflag;           // 0 line does not join, 1, joins. Not sure what large balues for non-lines mean - xscale?\r
+       char unkn4;                     // y-scale?\r
+       int num_points;         // different meaning for non-lines\r
+} structannotationbuf;\r
+*/\r
+\r
+\r
+struct annot_rec * annot_rec_new()\r
+{\r
+       struct annot_rec * nw = (struct annot_rec *)xmalloc(sizeof(struct annot_rec));\r
+       nw->type=-1;\r
+       nw->length=0;\r
+       nw->buf=NULL;\r
+       nw->annot_num = -1;\r
+       nw->text_length = 0;\r
+       nw->text = NULL;\r
+       nw->line_points=0;\r
+       nw->line_offset=0;\r
+       return nw;\r
+}\r
+\r
+void annot_rec_delete(struct annot_rec * annot_rec)\r
+{\r
+       //int i;\r
+       if (annot_rec==NULL)\r
+               return;\r
+       //for(i=0; i<annot_rec->line_points)\r
+       xfree(annot_rec->buf);\r
+       xfree(annot_rec->text);\r
+       xfree(annot_rec);\r
+}\r
+\r
+struct annotations * annotations_new()\r
+{\r
+       struct annotations * nw = (struct annotations*)xmalloc(sizeof(struct annotations));\r
+       nw->annot_list=NULL;\r
+       nw->header_buf=NULL;\r
+       nw->max_annot_num=0;\r
+       nw->num_annotations=0;\r
+       nw->read_recs_ok_flag=0;\r
+       nw->read_tail_ok_flag=0;\r
+       nw->stream_length=0;\r
+       nw->tail_buf_length=0;\r
+       nw->version=0;\r
+       return nw;\r
+}\r
+\r
+void annotations_delete(struct annotations * annots)\r
+{\r
+       int i;\r
+       if (annots==NULL)\r
+               return;\r
+\r
+       for (i=0; i<annots->num_annotations; i++)\r
+               annot_rec_delete(annots->annot_list[i]);\r
+       xfree(annots->annot_list);\r
+       xfree(annots->header_buf);\r
+       xfree(annots);\r
+}\r
+\r
+struct gpxpt* gpx_get_point(char* buf)\r
+// Convert the 12-byte location structure in annotations stream to GPS coordinates.\r
+{\r
+       struct gpxpt * pt = gpxpt_new();\r
+       double x;\r
+       double y;\r
+       double z;\r
+\r
+       if (buf==NULL)\r
+       {\r
+               printf("Trying to read line point from NULL\n");\r
+               gpxpt_delete(pt);\r
+               return NULL;\r
+       }\r
+\r
+       x= *(float *)(buf);\r
+       y= *(float *)(buf + 4);\r
+       z= *(float *)(buf + 8);\r
+\r
+       //printf("gpx_get_point x=%f y=%f z=%f\n",x,y,z);\r
+       pt->lat =  atan2(z,sqrt(pow(x,2)+ pow(y,2)))*180/M_PI;\r
+       pt->lon =  atan2(y,x)*180/M_PI;\r
+       // 6378137 is earths equatorial radius in meters\r
+       // set elevation for curiosity, but dont enable it with pt->use_elevation\r
+       pt->elevation= (sqrt(pow(x,2)+ pow(y,2)+ pow(z,2))-1)*6378137;\r
+       return pt;\r
+}\r
+\r
+struct annot_rec * read_annot_rec(FILE* annot_in_file, int version)\r
+{\r
+       int status;\r
+       int i;\r
+       int bit_flags=0;\r
+       int text_offset;\r
+       int text_len_offset;\r
+       int line_offset;\r
+       char* rec_type=NULL;\r
+\r
+       struct annot_rec * rec = annot_rec_new();\r
+       int head_len = 0;\r
+       switch (version)\r
+       {\r
+       case 3:\r
+               head_len = ANNOT_REC_HEAD_LEN;\r
+               text_len_offset = ANNOT_RECOS_TEXTLEN;\r
+               text_offset = ANNOT_RECOS_TEXT;\r
+               line_offset = 57;\r
+               break;\r
+       case 4:\r
+               head_len = ANNOT_REC_HEAD_LEN+4;\r
+               text_len_offset = ANNOT_RECOS_TEXTLEN+4;\r
+               text_offset = ANNOT_RECOS_TEXT+4;\r
+               line_offset = 57 + 4;\r
+               break;\r
+       default:\r
+               // FIXME version is passed as a param, should be handled there\r
+               printf("Unrecognised record format type %d, unable to process more annotations.\n", rec->type);\r
+               return NULL;\r
+               break;\r
+       }\r
+\r
+       // **********************\r
+       // Read the record header, up to begining of possible text\r
+       // **********************\r
+\r
+       rec->buf = (char*)xmalloc(head_len);\r
+       // This read can fail because I have miscalculated size or number of records\r
+       // So exit gracefully\r
+       status = readbytes(annot_in_file, rec->buf, head_len);\r
+       if (status!=head_len)\r
+       {\r
+               //FIXME\r
+//             gpx_write_file_trailer(gpx_out_file);\r
+               // exit(1)\r
+               // should do some cleaning up here\r
+               return rec;\r
+       }\r
+\r
+       rec->type = *(int*)(rec->buf+ANNOT_RECOS_TYPE);\r
+       if (rec->type > 3 )\r
+       {\r
+               printf("Unrecognised record type %d, unable to process more annotations\n", rec->type);\r
+               printbuf(rec->buf, head_len);\r
+               return NULL;\r
+       }\r
+\r
+       rec->annot_num = *(int*)(rec->buf+ANNOT_RECOS_ANUM);\r
+       // FIXME kludge, fit into the framework\r
+       bit_flags = *(int*)(rec->buf + 8);\r
+       rec->text_length = *(int*)(rec->buf+text_len_offset);\r
+       rec->line_points=0;\r
+       if (rec->type == ANNOT_TYPE_LINE)\r
+               rec->line_points = *(int*)(rec->buf+head_len-4);\r
+\r
+       // ***************************\r
+       // Calculate the record length\r
+       // ***************************\r
+\r
+       rec->length = annot_rec_len[rec->type] + 2*rec->text_length + 12*rec->line_points;\r
+       if (version > 3)\r
+               rec->length += 4;\r
+\r
+       // FIXME This is a kludge\r
+       if (opts.st_version_num>10)\r
+       {\r
+               if ( (rec->type == 1) || (rec->type == 4) )\r
+               {\r
+                       printf("Fudge: shortening 336 bytes from oval record length, but I dont know why.\n");\r
+                       (rec->length) -= 336;\r
+               }\r
+       }\r
+\r
+       if (rec->type == ANNOT_TYPE_LINE) \r
+               rec->line_offset = line_offset;\r
+\r
+       if (rec->type<4)\r
+               rec_type =annot_type_name[rec->type];\r
+       else \r
+               rec_type=NULL;\r
+\r
+       if (opts.verbose_flag > 4)\r
+               printf("Got annotation id %d, of type %d=%s, text length %d\n",\r
+                       rec->annot_num, rec->type, rec_type, rec->text_length);\r
+\r
+       // ****************************\r
+       // Read the rest of the record, from begining of possible text\r
+       // ****************************\r
+\r
+       rec->buf = (char*)xrealloc(rec->buf, rec->length);\r
+       status = readbytes(annot_in_file, rec->buf+head_len, rec->length - head_len);\r
+\r
+       if (status!=(rec->length - head_len))\r
+       {\r
+               printf("Unable to read next part of annotation record - quiting\n");\r
+               // fixme - we should stop processing annots but continue with rest\r
+               debug_pause();\r
+               exit(1);\r
+       }\r
+\r
+       if(rec->text_length>0)\r
+       {\r
+               rec->text=(char*)xmalloc(rec->text_length+1);\r
+               rec->text[rec->text_length]=0x0;\r
+               for (i=0;i<rec->text_length;i++)\r
+                       rec->text[i]=rec->buf[text_offset + 2*i];\r
+               str2ascii(rec->text);\r
+       }\r
+\r
+       if (opts.verbose_flag > 1)\r
+               print_annot_rec(rec);\r
+\r
+       if (opts.verbose_flag > 4)\r
+       {\r
+               printf("Recognised record with length %i\n",rec->length);\r
+               printbuf(rec->buf, rec->length);\r
+       }\r
+\r
+       return rec;\r
+}\r
+\r
+struct annotations * process_annotations_stream(char* annot_in_file_name)\r
+{\r
+       // Read the annotation file header\r
+       int i;\r
+       int status;\r
+       struct annot_rec * rec;\r
+       char* checkEOF;\r
+       int read_tail_buff=1;\r
+       FILE* annot_in_file=NULL;\r
+       struct annotations * annots = annotations_new();\r
+\r
+       annots->header_buf=(char*)xmalloc(ANNOT_FILE_HEAD_LEN);\r
+\r
+       if ((annot_in_file = fopen(annot_in_file_name, "rb")) == NULL)\r
+       {\r
+               fprintf(stderr, "Quitting because I cannot open %s\n", annot_in_file_name);\r
+               debug_pause();\r
+               exit(1);\r
+       }\r
+\r
+       status=readbytes(annot_in_file, annots->header_buf, ANNOT_FILE_HEAD_LEN);\r
+       if (status!=ANNOT_FILE_HEAD_LEN)\r
+       {\r
+               printf("Cant make any more sense of annotations stream, continuing\n");\r
+               return annots;\r
+       }\r
+       annots->stream_length += ANNOT_FILE_HEAD_LEN;\r
+\r
+       for (i=1; i<8; i++)\r
+               if ( annots->header_buf[i] != std_annotfile_header[i] )\r
+                       printf("Nonstandard annotations file header, header[%i]=0x%x, normal value is 0x%x\n",\r
+                                       i, annots->header_buf[i], std_annotfile_header[i] );\r
+\r
+       annots->version = *(int*)(annots->header_buf+4);\r
+       annots->num_annotations = *(int*)(annots->header_buf+8);\r
+\r
+       annots->annot_list = (struct annot_rec **)xmalloc(\r
+                                                               (annots->num_annotations)*sizeof(struct annot_rec*));\r
+\r
+       if (opts.verbose_flag > 1)\r
+       {\r
+               printf("Annotations file header, version %d, indicates %d annotations in file\n",\r
+                               annots->version, annots->num_annotations);\r
+       }\r
+\r
+       if (opts.verbose_flag > 4)\r
+       {\r
+               printf("Dumping file header:\n");\r
+               printbuf(annots->header_buf, ANNOT_FILE_HEAD_LEN);\r
+       }\r
+\r
+       /*\r
+       ** Read all the annotation records\r
+       */\r
+       annots->read_recs_ok_flag = 1;\r
+       for (i=0; i < annots->num_annotations; i++)\r
+       {\r
+           rec = read_annot_rec(annot_in_file, annots->version);\r
+\r
+               // current version of explore annots is a bit childish\r
+//             if (opts.explore_flag)\r
+//                     explore_annot(rec);\r
+               if (rec==NULL)\r
+               {\r
+                       annots->read_recs_ok_flag = 0;\r
+                       annots->num_annotations = i-1;\r
+                       read_tail_buff=0;\r
+                       break;\r
+               }\r
+\r
+               annots->annot_list[i] = rec;\r
+               annots->max_annot_num = __max(annots->max_annot_num, rec->annot_num);\r
+               annots->stream_length += rec->length;\r
+       }\r
+\r
+       // Check that we are at the end of annotation file\r
+       if (read_tail_buff)\r
+       {\r
+               checkEOF = xmalloc(4);\r
+               status=readbytes(annot_in_file, checkEOF, 4);\r
+               annots->stream_length += status;\r
+               if ( (status!=4) || (checkEOF[0]!=0) || (checkEOF[1]!=0)\r
+                               || (checkEOF[2]!=0) || (checkEOF[3]!=0) || (getc(annot_in_file)!=EOF) )\r
+               {\r
+                       fprintf (stderr, "Did not finish reading annotation file at EOF\n");\r
+               }\r
+               else\r
+                       annots->read_tail_ok_flag=1;\r
+               xfree(checkEOF);\r
+       }\r
+       fclose(annot_in_file);\r
+       return annots;\r
+}\r
diff --git a/st2gpx/src/annotations.h b/st2gpx/src/annotations.h
new file mode 100644 (file)
index 0000000..0fe4814
--- /dev/null
@@ -0,0 +1,181 @@
+/*\r
+       annotations.h\r
+\r
+       Extract data from MS Streets & Trips .est and Autoroute .axe files in GPX format.\r
+\r
+    Copyright (C) 2003 James Sherring, james_sherring@yahoo.com\r
+\r
+    This program is free software; you can redistribute it and/or modify\r
+    it under the terms of the GNU General Public License as published by\r
+    the Free Software Foundation; either version 2 of the License, or\r
+    (at your option) any later version.\r
+\r
+    This program is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+\r
+    You should have received a copy of the GNU General Public License\r
+    along with this program; if not, write to the Free Software\r
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA\r
+\r
+\r
+       This app depends on istorage & istorage-make from Pabs (pabs3@zip.to)\r
+       and James Clark's Expat xml parser from http://www.libexpat.org/.\r
+\r
+*/\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+#define ANNOT_FILE_HEAD_LEN 12\r
+// This needs to be long enough to get enough params to decide which record,\r
+// but no biger than the shortest record\r
+#define ANNOT_REC_HEAD_LEN 57 //19\r
+\r
+#define ANNOT_TYPE_LINE                0\r
+#define ANNOT_TYPE_OVAL                1\r
+#define ANNOT_TYPE_TEXT                2\r
+#define ANNOT_TYPE_CIRCLE      3\r
+\r
+#define REC_CLOSE_LEN 0\r
+// offsets for parameters in annotation recods\r
+#define ANNOT_RECOS_TYPE       0\r
+#define ANNOT_RECOS_ANUM       4\r
+#define ANNOT_RECOS_TEXTLEN    20\r
+#define ANNOT_RECOS_TEXT       24\r
+#define ANNOT_RECOS_LINENUMPOINTS 53\r
+#define ANNOT_RECOS_LINEJOINFLAG 48\r
+#define ANNOT_RECOS_XSCALE     48\r
+#define ANNOT_RECOS_YSCALE     52\r
+\r
+// + 12*NUM POINTS\r
+#define LINE_REC_LEN_V3 57\r
+#define LINE_REC_LEN_V4 61 //???\r
+\r
+\r
+//#define ANNOT_TYPE_LINE              0\r
+//#define ANNOT_TYPE_OVAL              1\r
+//#define ANNOT_TYPE_TEXT              2\r
+//#define ANNOT_TYPE_CIRCLE    3\r
+\r
+/*\r
+typedef struct annotations_file_head\r
+{\r
+       // always 0x2d001234\r
+       unsigned int uiunkn0;\r
+       // autoroute 2001: version=3\r
+       // autoroute 2003: version=4\r
+       unsigned int version;\r
+       // number of annotations in the stream\r
+       unsigned int c_annots;\r
+} tag_annotations_file_head;\r
+               \r
+typedef struct annotation_record_header\r
+{\r
+       // 0 = line\r
+       // 1 = Oval\r
+       // 2 = Textbox/Rectangle\r
+       // 3 = Circle\r
+       unsigned int type;\r
+       // 0x8 = show length\r
+       // 0x10 = order before roads\r
+       // (order defore other objects depends on file order (last highest) and obj type)\r
+       unsigned int bitflags;\r
+       int iunkn0;\r
+       int iunkn1;\r
+       // iunkn2 is only for version 10+ (9+?)\r
+       int iunkn2;\r
+       unsigned int text_len;\r
+       char text[];\r
+       // 0 =black\r
+       // 12=blue\r
+       unsigned int fill_color;\r
+       // 0 = none\r
+       // 1 = fill\r
+       // + some other high-byte flags?\r
+       int fill_flag;\r
+       //  0 = black\r
+       // 12 = blue\r
+       // 0d = yellow\r
+       unsigned int line color;\r
+       // 20*point size \r
+       unsigned int line_width;\r
+       // 00=none, \r
+       // 01=left, \r
+       // 02=right, \r
+       // 03=both;\r
+       int arrow_type;\r
+       int iunkn3;\r
+       // 01 is a joined line: the first & last points are joined\r
+       // 00 is a line-type\r
+       int closed_flag;\r
+       char cunkn0;\r
+       // number of points in the line\r
+       char c_line_points;\r
+       struct point_rec[];\r
+} tag_annotation_header;\r
+\r
+struct annot_line_point\r
+{\r
+       float x;\r
+       float y;\r
+       float z;\r
+}\r
+\r
+*/\r
+\r
+typedef struct annot_rec\r
+{\r
+       // ANNOT_TYPE_\r
+       int type;\r
+       int length;\r
+       char* buf;\r
+       int annot_num;\r
+       int text_length;\r
+       char* text;\r
+       int line_points;\r
+       // Pointer to the line-points data in buf, \r
+       // because it moves with different file formats.\r
+       int line_offset;\r
+} tag_annot_rec;\r
+\r
+struct annot_rec * annot_rec_new();\r
+void annot_rec_delete(struct annot_rec * annot_rec);\r
+\r
+typedef struct annotations\r
+{\r
+       int num_annotations;\r
+       int max_annot_num;\r
+       char* header_buf;\r
+       struct annot_rec ** annot_list;\r
+       int tail_buf_length;\r
+       char read_recs_ok_flag;\r
+       char read_tail_ok_flag;\r
+       int stream_length;\r
+       // This is the annotations version number, as stored in the annotations stream\r
+       int version;\r
+} tag_annotations;\r
+\r
+struct annotations * annotations_new();\r
+void annotations_delete(struct annotations * annots);\r
+struct gpxpt* gpx_get_point(char* buf);\r
+\r
+extern char std_annotfile_header[ANNOT_FILE_HEAD_LEN];\r
+extern char std_annot_linerec_header_v3[LINE_REC_LEN_V3];\r
+extern char std_annot_linerec_header_v4[LINE_REC_LEN_V4];\r
+\r
+//struct parameters {\r
+// Also need to include variable text length + line-points with these\r
+extern char* annot_type_name[4];\r
+extern char* gpxptypelabel[3];\r
+extern char * st_version[];\r
+\r
+//} tag_parameters;\r
+\r
+struct annotations * process_annotations_stream(char* annot_in_file_name);\r
+\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
diff --git a/st2gpx/src/bugs.txt b/st2gpx/src/bugs.txt
new file mode 100644 (file)
index 0000000..9c737d6
--- /dev/null
@@ -0,0 +1,21 @@
+st2gpx known issues\r
+\r
+\r
+Features:\r
+\r
+       Depends on ADO2.5\r
+\r
+       Known to work with Autoroute 2001, \r
+\r
+       Probably works with Autoroute 2002-3, Streets & Trips 2000-4, Mappoint 2000-4, \r
+       but not fully tested \r
+\r
+       Overwrites output files without warning\r
+\r
+\r
+Bugs:\r
+\r
+       Problem with input name "steph's  wedding.est",\r
+       but "steph's wedding.est" is ok (single space)\r
+       \r
+       with input file "Plesivec - Ple\9aivec.gpx" we fail to open the gpx as input
\ No newline at end of file
diff --git a/st2gpx/src/build.txt b/st2gpx/src/build.txt
new file mode 100644 (file)
index 0000000..a8830e1
--- /dev/null
@@ -0,0 +1,20 @@
+Build instructions:\r
+\r
+Build from VC++6 project.\r
+Important notes:\r
+* Use of 1-Byte struct alignment is required (rather than the MS default of 8)\r
+  due to the technique used here of overlaying a struct on an input buffer.\r
+* Use of #import at the top of pushpins.cpp requires setting the Visual Studio paths \r
+  to include ado libraries (c:\program files\common files\system\ado for me) \r
+  or setting the path explictitly in the #include statement.\r
+* Use of libexpat reqires a separate install of libexpat, and setting the \r
+  Visual Studio include and library paths to include libexpat. For me these are\r
+  D:\gpsbabel\Expat-1.95.7\Source\lib (for includes) and  D:\gpsbabel\Expat-1.95.7\Libs\r
+  (for libs).\r
+\r
+* Where possible, I have disabled MS language extensions (proj setting/c++/customize).\r
+  Exceptions are:\r
+       getopt.c (ms extensions are enabled only for win32)\r
+       properties.c (I have some unitialised arrays in file structs, I should clean this up)\r
+       pushpins.c (lots...)\r
+  But**** I have used various ms specific lib functions: __max, _fullpath, \r
diff --git a/st2gpx/src/contents.c b/st2gpx/src/contents.c
new file mode 100644 (file)
index 0000000..ee6bf4a
--- /dev/null
@@ -0,0 +1,554 @@
+/*\r
+       contents.c\r
+\r
+       Extract data from MS Streets & Trips .est and Autoroute .axe files in GPX format.\r
+\r
+    Copyright (C) 2003 James Sherring, james_sherring@yahoo.com\r
+\r
+    This program is free software; you can redistribute it and/or modify\r
+    it under the terms of the GNU General Public License as published by\r
+    the Free Software Foundation; either version 2 of the License, or\r
+    (at your option) any later version.\r
+\r
+    This program is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+\r
+    You should have received a copy of the GNU General Public License\r
+    along with this program; if not, write to the Free Software\r
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA\r
+\r
+\r
+       This app depends on istorage & istorage-make from Pabs (pabs3@zip.to)\r
+       and James Clark's Expat xml parser from http://www.libexpat.org/.\r
+\r
+*/\r
+#include <stdio.h>\r
+#include <memory.h>\r
+#include <stdlib.h>\r
+\r
+#include "st2gpx.h"\r
+#include "gpx.h"\r
+#include "contents.h"\r
+#include "annotations.h"\r
+\r
+char* buf2str(char* buf, int strlen)\r
+// make a null-terminated string from a buf\r
+{\r
+       char*str=NULL;\r
+       if (strlen==0)\r
+               return NULL;\r
+       str=(char*)xmalloc(strlen+1);\r
+       memcpy(str, buf, strlen);\r
+       str[strlen]=0;\r
+       return str;\r
+}\r
+\r
+struct contents * contents_new()\r
+{\r
+       struct contents * nw = (struct contents*)xmalloc(sizeof(struct contents));\r
+       nw->fully_parsed_flag=0;\r
+       nw->buf_len=0;\r
+       nw->buf=NULL;\r
+       nw->f_conts0=NULL;\r
+       nw->f_conts_array=NULL;\r
+       nw->f_pcbtext0=NULL;\r
+       nw->f_text0=NULL;\r
+       nw->f_conts1=NULL;\r
+       nw->f_text1=NULL;\r
+       nw->f_conts2=NULL;\r
+       // conts2->count_strings strings.\r
+       // Strings are not nul-terminated,\r
+       // but they are prefixed with their length.\r
+       nw->list_f_pcbtext=NULL;\r
+       nw->list_f_text=NULL;\r
+       nw->f_conts3=NULL;\r
+       // the end part of the buffer that has not been interpreted.\r
+       nw->rest=NULL;\r
+       return nw;\r
+}\r
+\r
+void contents_delete(struct contents * conts)\r
+{\r
+       xfree(conts->list_f_pcbtext);\r
+       xfree(conts->list_f_text);\r
+       xfree(conts->buf);\r
+       xfree(conts);\r
+}\r
+\r
+void print_f_contents0(struct f_contents0 * conts)\r
+{\r
+       struct gpxpt* map_cent=NULL;\r
+\r
+       printf("struct f_contents1:\n");\r
+       printf("usunkn0=%d\n", conts->usunkn0);\r
+       printf("map_center_X=%f\n", conts->map_center_X);\r
+       printf("map_center_Y=%f\n", conts->map_center_Y);\r
+       printf("map_center_Z=%f\n", conts->map_center_Z);\r
+       printf("map_scale=%f\n", conts->map_scale);\r
+       printf("iunkn0=%d\n", conts->iunkn0);\r
+       printf("iunkn1=%d\n", conts->iunkn1);\r
+       printf("iunkn2=%d\n", conts->iunkn2);\r
+       printf("iunkn3=%d\n", conts->iunkn3);\r
+       printf("iunkn4=%d\n", conts->iunkn4);\r
+       printf("iunkn5=%d\n", conts->iunkn5);\r
+       printf("iunkn6=%d\n", conts->iunkn6);\r
+       printf("legend_or_directions=%d\n", conts->legend_or_directions);\r
+       printf("iunkn7=%d\n", conts->iunkn7);\r
+       printf("iunkn8=%d\n", conts->iunkn8);\r
+       printf("iunkn9=%d\n", conts->iunkn9);\r
+       printf("usunkn2=%d\n", conts->usunkn2);\r
+       printf("iunkn10=%d\n", conts->iunkn10);\r
+       printf("iunkn11=%d\n", conts->iunkn11);\r
+       debug_pause();\r
+       printf("iunkn12=%d\n", conts->iunkn12);\r
+       printf("iunkn13=%d\n", conts->iunkn13);\r
+       printf("map_format_pannels=%d\n", conts->map_format_pannels);\r
+       printf("iunkn14=%d\n", conts->iunkn14);\r
+       printf("map_format_style=%d\n", conts->map_format_style);\r
+       printf("iunkn16=%d\n", conts->iunkn16);\r
+       printf("map_format_font_size=%d\n", conts->map_format_font_size);\r
+\r
+       printf("usunkn4=%d\n", conts->usunkn4);\r
+       printf("section_len=%d\n", conts->section_len);\r
+       printf("usunkn5=%d\n", conts->usunkn5);\r
+       printf("array_len=%d\n", conts->array_len);\r
+\r
+       map_cent = gpx_get_point((char*)(&conts->map_center_X));\r
+       printf("Got map center %f %f with scale %f (km?).\n",\r
+               map_cent->lat, map_cent->lon, conts->map_scale);\r
+       gpxpt_delete(map_cent);\r
+\r
+       printf("\n");\r
+       printf("\n");\r
+       debug_pause();\r
+}\r
+/* contents_array\r
+       printf("usunkn6=%d\n", conts->usunkn6);\r
+       printf("usunkn7=%d\n", conts->usunkn7);\r
+       printf("usunkn8=%d\n", conts->usunkn8);\r
+       printf("usunkn9=%d\n", conts->usunkn9);\r
+       printf("LastSetId=%d\n", conts->LastSetId);\r
+       printf("iunkn18=%d\n", conts->iunkn18);\r
+       printf("usunkn10=%d\n", conts->usunkn10);\r
+       printf("iunkn19=%d\n", conts->iunkn19);\r
+       printf("usunkn11=%d\n", conts->usunkn11);\r
+       printf("cbText0=%d\n", conts->cbText0);\r
+*/\r
+\r
+void print_f_contents1(struct f_contents1 * conts)\r
+{\r
+       printf("struct f_contents1:\n");\r
+\r
+       printf("iunkn20=%d\n", conts->iunkn20);\r
+       printf("cbText1=%d\n", conts->cbText1);\r
+\r
+       printf("\n");\r
+       debug_pause();\r
+}\r
+\r
+void print_f_contents2(struct f_contents2 * conts)\r
+{\r
+       printf("struct f_contents1:\n");\r
+\r
+       printf("iunkn21=%d\n", conts->iunkn21);\r
+       printf("count_strings=%d\n", conts->count_strings);\r
+\r
+       printf("\n");\r
+       debug_pause();\r
+}\r
+\r
+void print_f_contents3(struct f_contents3 * conts)\r
+{\r
+       printf("struct f_contents3:\n");\r
+\r
+       printf("usunkn15=%d\n", conts->usunkn15);\r
+       printf("usunkn16=%d\n", conts->usunkn16);\r
+       printf("usunkn17=%d\n", conts->usunkn17);\r
+       printf("usunkn18=%d\n", conts->usunkn18);\r
+       printf("cbCountryText=%d\n", conts->cbCountryText);\r
+\r
+       printf("\n");\r
+       debug_pause();\r
+}\r
+\r
+struct contents * parse_contents_buffer(char* buf, unsigned int buf_len)\r
+{\r
+       struct contents * conts = contents_new();\r
+       unsigned int buf_pos=0;\r
+       char* temp_str;\r
+       unsigned int i;\r
+\r
+       conts->buf = buf;\r
+       conts->buf_len=buf_len;\r
+\r
+       // *****************\r
+       // Parse f_contents0\r
+       // *****************\r
+\r
+       conts->f_conts0 = (struct f_contents0 *)(conts->buf);\r
+       buf_pos += sizeof(struct f_contents0);\r
+       if (buf_pos>(conts->buf_len))\r
+       {\r
+               printf("Oops, ran out of buffer with conts0.\n");\r
+               return conts;\r
+       }\r
+       if(opts.explore_flag)\r
+               print_f_contents0(conts->f_conts0);\r
+\r
+       // **************************\r
+       // Parse conts->f_conts_array\r
+       // **************************\r
+\r
+       conts->f_conts_array=(unsigned short *)(conts->buf + buf_pos);\r
+       buf_pos += conts->f_conts0->array_len;\r
+       if (buf_pos>(conts->buf_len))\r
+       {\r
+               printf("Oops, ran out of buffer with conts array.\n");\r
+               return conts;\r
+       }\r
+       if(opts.explore_flag)\r
+       {\r
+               printf("Dumping Contents array:\n");\r
+               printbuf((char*)(conts->f_conts_array), conts->f_conts0->array_len);\r
+\r
+               for(i=0; i< 3; i++)\r
+                       printf("Array[%d]=%d - unknown meaning\n", i, conts->f_conts_array[i]);\r
+\r
+               printf("n:=Array[3]=%d is number of user pushpin sets\n", (conts->f_conts_array)[3]);\r
+               \r
+//             for(i=0; i< (conts->f_conts_array[3]); i++)\r
+//                     printf("Array[%d]=%d is SetId for user PushpinSet[%d] \n", \r
+//                                     4+i,\r
+//                                     conts->f_conts_array[4+i],\r
+//                                     conts->f_conts_array[3] - i -1);        \r
+\r
+               for(i=0; i< (conts->f_conts_array[3]); i++)\r
+                       printf("Array[4+n-(%d)]=%d is SetId for user PushpinSet[%d]\n",\r
+                                       i, conts->f_conts_array[3+(conts->f_conts_array[3])-i], i);\r
+               \r
+               for(i=0; (4 + (conts->f_conts_array[3] +i)) < (conts->f_conts0->array_len)/2 ; i++)\r
+                       printf("Array[5+n+(%d)]=%d - unknown meaning\n",\r
+                                       i, conts->f_conts_array[4+(conts->f_conts_array[3])+i]);\r
+\r
+               debug_pause();\r
+\r
+//             printf("Dumping Contents array tail:\n");\r
+//             printbuf((char*)(conts->f_conts_array + 4 + conts->f_conts_array[3]), \r
+//                              (conts->f_conts0->array_len)-2*(4 + conts->f_conts_array[3])  );\r
+       }\r
+\r
+       // ************************\r
+       // Parse f_cbtext0, f_text0\r
+       // ************************\r
+\r
+       conts->f_pcbtext0=(unsigned char*)((conts->buf)+buf_pos);\r
+       buf_pos += sizeof(char);\r
+       if (buf_pos>(conts->buf_len))\r
+       {\r
+               printf("Oops, ran out of buffer with text0 size.\n");\r
+               return conts;\r
+       }\r
+\r
+       conts->f_text0=(conts->buf)+buf_pos;\r
+       buf_pos += *(conts->f_pcbtext0);\r
+       if (buf_pos>(conts->buf_len))\r
+       {\r
+               printf("Oops, ran out of buffer with text0.\n");\r
+               return conts;\r
+       }\r
+       // conts->f_cbtext0 is a *pointer* to text len\r
+       if(opts.explore_flag)\r
+       {\r
+               temp_str=buf2str(conts->f_text0, *(conts->f_pcbtext0));\r
+               printf("Got Text0='%s'\n", temp_str);\r
+               xfree(temp_str);\r
+               temp_str=NULL;\r
+       }\r
+\r
+       // *****************\r
+       // Parse f_contents1\r
+       // *****************\r
+\r
+       conts->f_conts1 = (struct f_contents1 *)(conts->buf+buf_pos);\r
+       buf_pos += sizeof(struct f_contents1);\r
+       if (buf_pos>(conts->buf_len))\r
+       {\r
+               printf("Oops, ran out of buffer with conts1.\n");\r
+               return conts;\r
+       }\r
+       if(opts.explore_flag)\r
+               print_f_contents1(conts->f_conts1);\r
+\r
+       // *************\r
+       // Parse f_text1\r
+       // *************\r
+\r
+       conts->f_text1 = (conts->buf)+buf_pos;\r
+       buf_pos += conts->f_conts1->cbText1;\r
+       if (buf_pos>(conts->buf_len))\r
+       {\r
+               printf("Oops, ran out of buffer with text1.\n");\r
+               return conts;\r
+       }\r
+       if(opts.explore_flag)\r
+       {\r
+               temp_str=buf2str(conts->f_text1, conts->f_conts1->cbText1);\r
+               printf("Got Text1='%s'\n", temp_str);\r
+               xfree(temp_str);\r
+               temp_str=NULL;\r
+       }\r
+\r
+       // *****************\r
+       // Parse f_contents2\r
+       // *****************\r
+\r
+       conts->f_conts2 = (struct f_contents2 *)((conts->buf)+buf_pos);\r
+       buf_pos += sizeof(struct f_contents2);\r
+       if (buf_pos>(conts->buf_len))\r
+       {\r
+               printf("Oops, ran out of buffer with conts2.\n");\r
+               return conts;\r
+       }\r
+       if(opts.explore_flag)\r
+               print_f_contents2(conts->f_conts2);\r
+\r
+       // ***************************************\r
+       // Parse list_f_cbtext[] and list_f_text[]\r
+       // ***************************************\r
+\r
+       conts->list_f_pcbtext=(unsigned char**)xmalloc((conts->f_conts2->count_strings)*sizeof(unsigned char*));\r
+       conts->list_f_text=(char**)xmalloc((conts->f_conts2->count_strings)*sizeof(char*));\r
+       // initialise just incase we dont make it through the parse loop\r
+       for(i=0; i<(conts->f_conts2->count_strings); i++)\r
+       {\r
+               conts->list_f_pcbtext[i]=NULL;\r
+               conts->list_f_text[i]=NULL;\r
+       }\r
+       for(i=0; i<(conts->f_conts2->count_strings); i++)\r
+       {\r
+               // list_f_cbtext[i] is a *pointer* to text len\r
+               conts->list_f_pcbtext[i]=(unsigned char*)(conts->buf+buf_pos);\r
+               buf_pos += sizeof(unsigned char);\r
+               if (buf_pos>(conts->buf_len))\r
+               {\r
+                       printf("Oops, ran out of buffer with text[%d] size.\n", i);\r
+                       return conts;\r
+               }\r
+               conts->list_f_text[i]=(conts->buf)+buf_pos;\r
+               buf_pos += conts->list_f_pcbtext[i][0];\r
+               if (buf_pos>(conts->buf_len))\r
+               {\r
+                       printf("Oops, ran out of buffer with text%d.\n", i);\r
+                       return conts;\r
+               }\r
+               if(opts.explore_flag)\r
+               {\r
+                       temp_str = buf2str(conts->list_f_text[i], *(conts->list_f_pcbtext[i]));\r
+                       printf("Got list_text[%d]='%s'\n", i, temp_str);\r
+                       xfree(temp_str);\r
+               }\r
+       }\r
+\r
+       // **************************\r
+       // Parse pusunkn0 and piunkn1\r
+       // **************************\r
+\r
+    conts->pusunkn0 = (unsigned short*)(conts->buf+buf_pos);\r
+       \r
+       buf_pos += sizeof(unsigned short);\r
+       if (buf_pos>(conts->buf_len))\r
+       {\r
+               printf("Oops, ran out of buffer with pusunkn0.\n");\r
+               return conts;\r
+       }\r
+       if(opts.explore_flag)\r
+               printf("usunkn0=%d\n", *(conts->pusunkn0) );\r
+\r
+       if(*(conts->pusunkn0) == 1)\r
+       {\r
+               conts->piunkn1 = (int*)((conts->buf)+buf_pos);\r
+               buf_pos += sizeof(int);\r
+               if (buf_pos>(conts->buf_len))\r
+               {\r
+                       printf("Oops, ran out of buffer with piunkn1.\n");\r
+                       return conts;\r
+               }\r
+               if(opts.explore_flag)\r
+                       printf("iunkn1=%d\n", *(conts->piunkn1) );\r
+       }\r
+\r
+       // *****************\r
+       // Parse f_contents2\r
+       // *****************\r
+\r
+       conts->f_conts3 = (struct f_contents3 *)(conts->buf+buf_pos);\r
+       buf_pos += sizeof(struct f_contents3);\r
+       if (buf_pos>(conts->buf_len))\r
+       {\r
+               printf("Oops, ran out of buffer with conts3.\n");\r
+               return conts;\r
+       }\r
+       if(opts.explore_flag)\r
+               print_f_contents3(conts->f_conts3);\r
+\r
+       // *****************\r
+       // Parse CountryText\r
+       // *****************\r
+\r
+       conts->CountryText = (conts->buf)+buf_pos;\r
+       buf_pos += conts->f_conts3->cbCountryText;\r
+       if (buf_pos>(conts->buf_len))\r
+       {\r
+               printf("Oops, ran out of buffer with text[%d].\n", conts->f_conts2->count_strings);\r
+               return conts;\r
+       }\r
+       if(opts.explore_flag)\r
+       {\r
+               temp_str=buf2str(conts->CountryText, conts->f_conts3->cbCountryText);\r
+               if(opts.explore_flag)\r
+               printf("Got CountryText='%s'\n", temp_str);\r
+               xfree(temp_str);\r
+               temp_str=NULL;\r
+       }\r
+\r
+       if (buf_pos == conts->buf_len)\r
+               conts->fully_parsed_flag=1;\r
+       else\r
+       {\r
+               printf("Unexpected %d bytes of contents buffer still remaining.\n", \r
+                               (conts->buf_len)-buf_pos);\r
+               printbuf((conts->buf)+buf_pos, (conts->buf_len)-buf_pos);\r
+       }\r
+\r
+       return conts;\r
+}\r
+\r
+struct contents * read_contents(char* conts_file_name)\r
+{\r
+       FILE* conts_file=NULL;\r
+       const unsigned int max_conts_buf=1000;\r
+       int readbyte=0;\r
+       unsigned int buf_pos=0;\r
+       char* buf=(char*)xmalloc(max_conts_buf);\r
+       struct contents * conts=NULL;\r
+\r
+       // ****************************************\r
+       // Read the Contents stream into the buffer\r
+       // ****************************************\r
+\r
+       if ((conts_file = fopen(conts_file_name, "rb")) == NULL)\r
+       {\r
+               fprintf(stderr, "Cannot open property file %s\n", conts_file_name);\r
+               return NULL;\r
+       }\r
+\r
+       if ((readbyte = getc(conts_file))!=EOF)\r
+       {\r
+               do {\r
+                       buf[buf_pos]=(char)readbyte;\r
+                       buf_pos++;\r
+                       if (buf_pos>max_conts_buf-1)\r
+                       {\r
+                               printf("oops, I didn't allocate enough buffer space for contents...\n");\r
+                               break;\r
+                       }\r
+               } while ((readbyte = getc(conts_file))!=EOF);\r
+\r
+       }\r
+       fclose(conts_file);\r
+\r
+       printf("Read %d bytes in contents stream %s\n", buf_pos, conts_file_name);\r
+       if (opts.verbose_flag>4)\r
+       {\r
+               printbuf(buf, buf_pos);\r
+               printf("Now trying to enterpret this data...\n");\r
+               debug_pause();\r
+       }\r
+\r
+       conts = parse_contents_buffer(buf, buf_pos);\r
+\r
+       debug_pause();\r
+       return conts;\r
+}\r
+\r
+struct contents * contents_insert_ppinset(struct contents * old_conts, unsigned short newSetId)\r
+{\r
+       // After inserting pushpins into UserData db,\r
+       // we need to update the Contents structure to include the new pushpin set\r
+       // in the list of objects to display.\r
+       // Otherwise the new pushpins will no be visible or editable.\r
+       struct contents * nw_conts=NULL;\r
+       char* nw_buf=NULL;\r
+       unsigned int nw_buf_len=0;\r
+       unsigned int insert_position=0;\r
+       unsigned int arraylen_os=0;\r
+\r
+       if (old_conts==NULL)\r
+       {\r
+               printf("Contents buffer is empty???. The outut file will have a corrupted pushpin set.\n");\r
+               return NULL;\r
+       }\r
+\r
+       if (old_conts->fully_parsed_flag == 0)\r
+       {\r
+               printf("Warning - modifying a contents stream that is not fully parsed.\n");\r
+               // Actually, we only need to have parsed as far as old_conts->f_conts_array,\r
+               // but best to be safe.\r
+               if(old_conts->CountryText !=NULL)\r
+                       printf("...but I seem to have parsed enough to continue.\n");\r
+               else\r
+               {\r
+                       printf("I have not parsed enough to continue. The outut file will have a corrupted pushpin set.\n");\r
+                       return NULL;\r
+               }\r
+       }\r
+\r
+       nw_buf_len = old_conts->buf_len  + 2*sizeof(unsigned char);\r
+       nw_buf = (char *)xmalloc(nw_buf_len);\r
+\r
+       // insert after f_conts_array[3], ie at f_conts_array+4\r
+       insert_position = ((char*)(old_conts->f_conts_array+4)-(old_conts->buf));\r
+\r
+       memcpy(nw_buf, old_conts->buf, insert_position);\r
+       memcpy(nw_buf + insert_position, &newSetId, sizeof(unsigned short));\r
+       memcpy(nw_buf + insert_position + sizeof(unsigned short),\r
+                       old_conts->buf + insert_position,\r
+                       old_conts->buf_len - insert_position);\r
+\r
+       // set the size of the contents aray\r
+       arraylen_os = (char*)&(old_conts->f_conts0->array_len) - old_conts->buf;\r
+       *(nw_buf + arraylen_os) += sizeof(unsigned short);\r
+\r
+       // increase the number of pushpin sets in f_conts_array[3]\r
+       *(nw_buf + insert_position - sizeof(unsigned short)) +=1;\r
+\r
+       nw_conts=parse_contents_buffer(nw_buf, nw_buf_len);\r
+\r
+       return  nw_conts;\r
+}\r
+\r
+void write_contents(struct contents * conts, char* conts_file_name)\r
+{\r
+       FILE* conts_out_file;\r
+       int status;\r
+\r
+       //printf("Writing new Contents stream to %s\n", conts_file_name);\r
+\r
+       if ((conts_out_file = fopen(conts_file_name, "wb")) == NULL) {\r
+           fprintf(stderr, "Cannot open %s\n", conts_file_name);\r
+                  fflush(stdout);\r
+                       debug_pause();\r
+           exit(1);\r
+          }\r
+\r
+       status = fwrite(conts->buf, conts->buf_len, 1, conts_out_file);\r
+       if (status != 1)\r
+               printf("expected to write %d, actually wrote %d\n", conts->buf_len, status*(conts->buf_len));\r
+       else\r
+               printf("Wrote %d bytes to new contents stream in %s\n", conts->buf_len, conts_file_name);\r
+\r
+       fclose(conts_out_file);\r
+\r
+}
\ No newline at end of file
diff --git a/st2gpx/src/contents.h b/st2gpx/src/contents.h
new file mode 100644 (file)
index 0000000..3a30642
--- /dev/null
@@ -0,0 +1,224 @@
+/*\r
+       contents.h\r
+\r
+       Extract data from MS Streets & Trips .est and Autoroute .axe files in GPX format.\r
+\r
+    Copyright (C) 2003 James Sherring, james_sherring@yahoo.com\r
+\r
+    This program is free software; you can redistribute it and/or modify\r
+    it under the terms of the GNU General Public License as published by\r
+    the Free Software Foundation; either version 2 of the License, or\r
+    (at your option) any later version.\r
+\r
+    This program is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+\r
+    You should have received a copy of the GNU General Public License\r
+    along with this program; if not, write to the Free Software\r
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA\r
+\r
+\r
+       This app depends on istorage & istorage-make from Pabs (pabs3@zip.to)\r
+       and James Clark's Expat xml parser from http://www.libexpat.org/.\r
+\r
+*/\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+typedef struct f_contents0\r
+{\r
+       // @ 00\r
+       unsigned short usunkn0; // 0c 00\r
+       float   map_center_X;\r
+       float   map_center_Y;\r
+       float   map_center_Z;\r
+       // in km?\r
+       float   map_scale;\r
+       // @ 12\r
+       int             iunkn0; // 00 00 00 00\r
+       // next two are interesting when there are ppins imported from a file\r
+       // got 180213657 = ABDD799\r
+       // and -1073143305 = C00921F7\r
+       int             iunkn1;\r
+       int             iunkn2;\r
+       int             iunkn3; // 20 03 00 00\r
+       // @ 22\r
+       int             iunkn4; // 01 00 00 00\r
+       int             iunkn5; // 06 00 00 00\r
+       int             iunkn6; // c4 09 00 00\r
+       // 0=legend/route directions if\r
+       // 1=no legend\r
+       // (related to iunkn13)\r
+       unsigned short legend_or_directions; // 00 00 / 01 00\r
+       // @ 30\r
+       int             iunkn7; // 01 00 00 00\r
+       int             iunkn8; // 06 00 00 00\r
+       int     iunkn9; // e4 0c 00 00 for eur8, c4 09 00 00 for usa9\r
+       unsigned short usunkn2; // 00 00\r
+       int             iunkn10; // 1\r
+       // @ 42\r
+       int             iunkn11; // 06 00 00 00\r
+       int     iunkn12; // XX XX 00 00\r
+       unsigned short iunkn13; // 00 00\r
+\r
+       // Does not seem to match these values...\r
+       //GeoPaneState Value Description \r
+       //geoPaneLegend 0 Legend is displayed \r
+       //geoPaneNearbyPlaces 2 Find Nearby Places pane is displayed \r
+       //geoPaneNone 3 Only the map is displayed \r
+       //geoPaneRoutePlanner 1 Route Planner pane is displayed \r
+       //geoPaneTerritory 4 Territory Manager pane is displayed \r
+\r
+       // 0=no legend or show route directions ( iunkn6)\r
+       // 1=normal\r
+       // 2=route planner\r
+       // 4=find nearby places\r
+       int             map_format_pannels;\r
+       // @ 50\r
+       int             iunkn14; // 1 0 4 0\r
+\r
+//     GeoMapStyle Value Description \r
+//     geoMapStyleData 2 Data map \r
+//     geoMapStylePolitical 4 Political map \r
+//     geoMapStyleRoad 0 Road map \r
+//     geoMapStyleRoadData 1 Road and data map \r
+//     geoMapStyleTerrain 3 Terrain map \r
+  \r
+       // 0 = Road\r
+       // 3 = Terrain\r
+       // 4 = Political\r
+       int     map_format_style;\r
+       int             iunkn16; // 1 0 4 0\r
+       // 0-4,\r
+       // 0=largest\r
+       // 4=smallest\r
+       int             map_format_font_size; // 03 00 00 00\r
+       // @ 60\r
+       unsigned short usunkn4;    //03 00\r
+       //length of section from here until end of EUR/USA string\r
+       int             section_len;\r
+       unsigned short usunkn5; // 03 00\r
+       // array_len = 0x14 + 2*num ppin sets\r
+       // if array_len=0x14, str1@81. if array_len=0x16 str1@83\r
+       unsigned int            array_len;              // xx 00 00 00 (14/16)\r
+} tag_f_contents0;\r
+\r
+/*\r
+typedef struct f_contents_array\r
+{\r
+       unsigned short usunkn6; // 03 00\r
+       unsigned short usunkn7; // 02/01 00\r
+       // @ 70\r
+       unsigned short usunkn8; // 00 00\r
+       // number of user ppin sets\r
+       unsigned short usunkn9; // 00/01 00 (0 for empty, 1 for ppins?)\r
+       // from UserData/GEODB_LastId/LastSetId\r
+       // note the size mismatch: short/long\r
+       unsigned short LastSetId;\r
+       unsigned short usunkn9_1; // 0\r
+       unsigned short usunkn9_2; // 0\r
+       unsigned short usunkn10; // 0\r
+       unsigned short usunkn10_1; // 0\r
+       unsigned short usunkn10_2; // 0\r
+       int             iunkn19;                 // 3\r
+       // @ 80\r
+       unsigned short usunkn11; // 0\r
+} tag_f_contents_array;\r
+*/\r
+\r
+// +   unsigned char cbText0;\r
+// + cbText0 bytes of text\r
+\r
+// @ 8b\r
+\r
+typedef struct f_contents1\r
+{\r
+       int             iunkn20;                 // 00 00 00 00/ff ff ff ff\r
+       unsigned char cbText1;\r
+} tag_f_contents1;\r
+\r
+// + cbText1 bytes of text\r
+// @ 98\r
+typedef struct f_contents2\r
+{\r
+       int             iunkn21;                 // ff ff ff ff\r
+       // This is a count of strings before contents3\r
+       unsigned short count_strings; // 3\r
+} tag_f_contents2;\r
+\r
+//     unsigned char cbText2;\r
+// + cbText2 bytes of text\r
+// @ a6\r
+// + unsigned char cbText3\r
+// + cbText3 bytes of text\r
+// @ ae\r
+// + optional ? unsigned char cbText4\r
+// + optional ? cbText4 bytes of text\r
+// @ b7\r
+\r
+//+    unsigned short usunkn14;\r
+// + int (if usunkn14)\r
+\r
+typedef struct f_contents3\r
+{\r
+       unsigned short usunkn15;\r
+       unsigned short usunkn16;\r
+       unsigned short usunkn17;\r
+       unsigned short usunkn18;\r
+       // FIXME + an extra short for usa9, + 2 extra shorts for usa10\r
+       unsigned char cbCountryText;\r
+} tag_f_contents3;\r
+\r
+// + cbText5 bytes of text: USA/EUR\r
+\r
+// more for USA9\r
+// + int\r
+// + unsigned char cbText6\r
+// + cbText6 bytes of text\r
+// + unsigned char cbText7\r
+// + cbText7 bytes of text : path to html: html export file?\r
+// + 0x40 bytes\r
+\r
+\r
+typedef struct contents\r
+{\r
+       int fully_parsed_flag;\r
+       unsigned int buf_len;\r
+       // The data as read from the contents stream.\r
+       char* buf;\r
+       struct f_contents0 * f_conts0;\r
+       unsigned short * f_conts_array;\r
+       unsigned char * f_pcbtext0;\r
+       char* f_text0;\r
+       struct f_contents1 * f_conts1;\r
+       char* f_text1;\r
+       struct f_contents2 * f_conts2;\r
+       // Lengths for conts2->count_strings number of strings.\r
+       // Note that this is array of *pointers* to string-length\r
+       unsigned char ** list_f_pcbtext;\r
+       // conts2->count_strings number of strings.\r
+       // Strings are not null-terminated,\r
+       // but they are prefixed with their length.\r
+       char ** list_f_text;\r
+       // Normally 0, sometimes 1\r
+       unsigned short * pusunkn0;\r
+       // Only when usunkn0=1 ???\r
+       int * piunkn1;\r
+       struct f_contents3 * f_conts3;\r
+       char * CountryText;\r
+       // The end part of the buffer that has not been interpreted.\r
+       char* rest;\r
+} tag_contents;\r
+\r
+struct contents * read_contents(char* conts_file_name);\r
+struct contents * contents_insert_ppinset(struct contents * old_conts, unsigned short newSetId);\r
+void write_contents(struct contents * conts, char* conts_file_name);\r
+void contents_delete(struct contents * conts);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
diff --git a/st2gpx/src/debug.c b/st2gpx/src/debug.c
new file mode 100644 (file)
index 0000000..e1cf06f
--- /dev/null
@@ -0,0 +1,589 @@
+/*\r
+       debug.c\r
+\r
+       Extract data from MS Streets & Trips .est and Autoroute .axe files in GPX format.\r
+\r
+    Copyright (C) 2003 James Sherring, james_sherring@yahoo.com\r
+\r
+    This program is free software; you can redistribute it and/or modify\r
+    it under the terms of the GNU General Public License as published by\r
+    the Free Software Foundation; either version 2 of the License, or\r
+    (at your option) any later version.\r
+\r
+    This program is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+\r
+    You should have received a copy of the GNU General Public License\r
+    along with this program; if not, write to the Free Software\r
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA\r
+\r
+\r
+       This app depends on istorage & istorage-make from Pabs (pabs3@zip.to)\r
+       and James Clark's Expat xml parser from http://www.libexpat.org/.\r
+\r
+*/\r
+#include <stdio.h>\r
+#include <memory.h>\r
+#include <malloc.h>\r
+\r
+#include "gpx.h"\r
+#include "st2gpx.h"\r
+#include "getopt.h"\r
+#include "properties.h"\r
+#include "pushpins.h"\r
+#include "ppinutil.h"\r
+#include "annotations.h"\r
+#include "journey.h"\r
+\r
+void debug_pause()\r
+{\r
+       char c;\r
+       if (opts.debug_wait_flag)\r
+       {\r
+               fprintf(stderr, "Hit Enter key to continue\n");\r
+               c=getchar();\r
+               // a way to stop pausing\r
+               if (c=='q')\r
+                       opts.debug_wait_flag=0;\r
+       }\r
+}\r
+\r
+int fixhex(char c)\r
+{\r
+// gcc (version?) does not print single byte hex values properly\r
+// eg 0xe3 prints as 0xFFFFFFE3\r
+// this is only a problem for values above 0x80\r
+// Or maybe that is the proper handling of unsigned?\r
+// Aaaahhh. I should use %u for printing unsigned... but the hex problem is still there\r
+       if(c & 0x80)\r
+       {\r
+               return ((int)c-0xFFFFFF00);\r
+       } else\r
+               return c;\r
+}\r
+\r
+void printbuf(char* buf, int len)\r
+{\r
+//     unsigned i;\r
+       int i;\r
+       printf("     0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F\n");\r
+       printf("    -----------------------------------------------");\r
+       for(i=0; i<len; i++)\r
+       {\r
+               if (((i+1) & 0x0f) == 0x1)\r
+                       printf("\n%2x| ",i/16);\r
+               printf("%2x ",fixhex(buf[i]));\r
+       }\r
+       printf("\n\n");\r
+}\r
+\r
+void printbufwide(char* buf, int len)\r
+{\r
+       int i;\r
+       for(i=0; i<len; i++)\r
+       {\r
+               printf("%2x ",fixhex(buf[i]));\r
+       }\r
+       printf("\n\n");\r
+}\r
+\r
+void printbufhigh(char* buf, int len)\r
+{\r
+       int i;\r
+       for(i=0; i<len; i++)\r
+       {\r
+               printf("%02x %02x\n", i, fixhex(buf[i]));\r
+       }\r
+       printf("\n\n");\r
+}\r
+\r
+void printbufasfloat(char* buf, int len)\r
+{\r
+//     unsigned i;\r
+       int i;\r
+//     printf("     0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F\n");\r
+//     printf("    -----------------------------------------------");\r
+       for(i=0; i<len-3; i++)\r
+       {\r
+               if (((i+1) & 0x03) == 0x1)\r
+                       printf("\n%2x| ",i);\r
+               printf("%f  ", *(float*)(buf+i));\r
+               fflush(stdout);\r
+       }\r
+       printf("\n\n");\r
+}\r
+\r
+void printfloatbuf(float* fbuf, int len)\r
+{\r
+//     unsigned i;\r
+       int i;\r
+//     printf("     0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F\n");\r
+//     printf("    -----------------------------------------------");\r
+       for(i=0; i<len; i++)\r
+       {\r
+               if (((i+1) & 0x03) == 0x1)\r
+                       printf("\n%2x| ",4*i);\r
+               printf("%f  ", fbuf[i]);\r
+               fflush(stdout);\r
+       }\r
+       printf("\n\n");\r
+}\r
+\r
+void printpoints(char* buf, int numpts)\r
+{\r
+       int i;\r
+//     int j;\r
+       struct gpxpt* pt;\r
+       printf("Latitude  Longitude Height");\r
+       printf("\n");\r
+       printf("--------------------------\n");\r
+       for(i=0; i<numpts; i++)\r
+       {\r
+               pt = gpx_get_point(buf + 12*i);\r
+               printf("%f %f %f \n",pt->lat, pt->lon, pt->elevation);\r
+               gpxpt_delete(pt);\r
+       }\r
+       printf("\n\n");\r
+}\r
+\r
+void printpointsbuf(char* buf, int len)\r
+{\r
+//     unsigned i;\r
+//     unsigned j;\r
+       int i;\r
+       int j;\r
+       printf("     0  1  2  3  4  5  6  7  8  9  A  B\n");\r
+       printf("    -----------------------------------");\r
+       for(i=0; i<len; i++)\r
+       {\r
+               printf("\n%2x| ",i);\r
+       //      printf("\n");\r
+               for (j=0; j<12; j++)\r
+               {\r
+                       printf("%2x ",fixhex(buf[12*i+j]));\r
+                       fflush(stdout);\r
+               }\r
+       }\r
+       printf("\n\n");\r
+}\r
+\r
+void printbufaspoints(char* buf, int buflen)\r
+{\r
+       int i;\r
+//     int j;\r
+       struct gpxpt * pt;\r
+       printf("Latitude  Longitude Height");\r
+       printf("\n");\r
+       printf("--------------------------\n");\r
+       for(i=0; i<buflen-11; i++)\r
+       {\r
+               pt = gpx_get_point(buf + 12*i);\r
+               printf("%#02x %f N %f E %f m \n", i, pt->lat, pt->lon, pt->elevation);\r
+               gpxpt_delete(pt);\r
+               fflush(stdout);\r
+       }\r
+       printf("\n\n");\r
+}\r
+\r
+void printnzbuf(char* buf, int len)\r
+{\r
+// print non-zero values in the buffer\r
+//     unsigned i;\r
+       int i;\r
+       for(i=0; i<len; i++)\r
+       {\r
+//             if (buf[i] != 0) printf("Buf[%x]=%2x ",fixhex(i), fixhex(buf[i]));\r
+               if (buf[i] != 0) printf("Buf[%x]=%2x ",i, fixhex(buf[i]));\r
+       }\r
+       printf("\n");\r
+}\r
+\r
+//void printnzhead(struct annot_rec rec)\r
+//{\r
+//     printnzbuf(rec.buf, annot_head_len[rec.type]);\r
+//}\r
+\r
+void explore_annot(struct annot_rec * rec)\r
+{\r
+       char* header;\r
+       char* tail;\r
+       int taillength;\r
+\r
+       header = (char*)xmalloc(ANNOT_REC_HEAD_LEN);\r
+       memcpy(header, rec->buf, ANNOT_RECOS_TEXT);\r
+       memcpy(header+ANNOT_RECOS_TEXT+2*rec->text_length, rec->buf,\r
+               ANNOT_REC_HEAD_LEN-ANNOT_RECOS_TEXT);\r
+\r
+       tail = rec->buf+ANNOT_REC_HEAD_LEN+2*rec->text_length;\r
+       taillength = rec->length - ANNOT_REC_HEAD_LEN+2*rec->text_length;\r
+\r
+       printf("Record buffer\n", annot_type_name[rec->type]);\r
+       printbuf(rec->buf, rec->length);\r
+       printf("Record high buffer\n", annot_type_name[rec->type]);\r
+       printbufhigh(rec->buf, rec->length);\r
+       printf("Record wide header:\n", annot_type_name[rec->type]);\r
+       printbufwide(header, ANNOT_REC_HEAD_LEN);\r
+       printf("Record tail:\n");\r
+       printbuf(tail, taillength);\r
+       printf("Record wide tail:\n");\r
+       printbufwide(tail, taillength);\r
+       printf("Record tail as floats:\n");\r
+       printbufasfloat(tail, taillength);\r
+       printf("Record tail as points:\n");\r
+       printbufaspoints(tail, taillength);\r
+//     if (rec->type == ANNOT_TYPE_TEXT)\r
+//     {\r
+               //printfloatbuf((float*)(tail+3), taillength/4 -1);\r
+//     }\r
+//     else if (rec->type == ANNOT_TYPE_OVAL )\r
+//             printfloatbuf((float*)(tail+3), taillength/4 -1);\r
+//     else if (rec->type == ANNOT_TYPE_CIRCLE ))\r
+//             printfloatbuf((float*)(tail+3), taillength/4 -1);\r
+       xfree(header);\r
+}\r
+\r
+void print_f_jour_header(struct f_jour_header * head)\r
+{\r
+       printf("struct f_jour_header:\n");\r
+       printf("iunkn0 %x=%d\n", head->iunkn0, head->iunkn0);\r
+       printf("iunkn1 %x=%d\n", head->iunkn1, head->iunkn1);\r
+       printf("iunkn2 %x=%d\n", head->iunkn2, head->iunkn2);\r
+       printf("iunkn3 %x=%d\n", head->iunkn3, head->iunkn3);\r
+       printf("cpoints %x=%d\n", head->cpoints, head->cpoints);\r
+       printf("iunkn4 %x=%d\n", head->iunkn4, head->iunkn4);\r
+       printf("iunkn5 %x=%d\n", head->iunkn5, head->iunkn5);\r
+       printf("iunkn6 %x=%d\n", head->iunkn6, head->iunkn6);\r
+}\r
+\r
+void print_f_jour_pt_head(struct f_jour_pt_head * pt_head)\r
+{\r
+//     double x;\r
+       printf("struct f_jour_pt_head:\n");\r
+       printf("UdId %d\n", pt_head->UdId);\r
+       printf("stop_dur_secs %d\n",  pt_head->stop_dur_secs);\r
+       printf("iunkn0 %#x=%d\n", pt_head->iunkn0, pt_head->iunkn0);\r
+       printf("sched_arrive_flag %d\n", pt_head->sched_arrive_flag);\r
+       printf("sched_depart_flag %d\n", pt_head->sched_depart_flag);\r
+       printf("arrive_time_secs %d\n", pt_head->arrive_time_secs); \r
+       printf("depart_time_secs %d\n", pt_head->depart_time_secs);\r
+       printf("iunkn1 %#x=%d\n", pt_head->iunkn1, pt_head->iunkn1);\r
+//     x = pt_head->unkn_scaled_lon;\r
+//     x = x*360/0x10000;\r
+//     x = x/0x10000;\r
+       printf("scaled_lon %d gives lon %f\n", \r
+                       pt_head->scaled_lon, scaled2deg(pt_head->scaled_lon));\r
+//     x = (pt_head->unkn_scaled_lat*360/0x10000);\r
+//     x = x/0x10000;\r
+       printf("scaled_lat %d gives lat %f\n", \r
+                       pt_head->scaled_lat, scaled2deg(pt_head->scaled_lat));\r
+       printf("cbtext1 %d\n",pt_head->cbtext1);\r
+       printbuf((char*)pt_head, sizeof(struct f_jour_pt_head));\r
+}\r
+\r
+void print_f_jour_pt_tail(struct f_jour_pt_tail * pt_tail)\r
+{\r
+       printf("struct f_jour_pt_tail: \n");\r
+       printf("route_rd_pref %x\n",pt_tail->route_rd_pref);\r
+       printf("iunkn0 %x=%d\n", pt_tail->iunkn0, pt_tail->iunkn0);\r
+       printf("iunkn1 %x=%d\n", pt_tail->iunkn1, pt_tail->iunkn1);\r
+       printf("iunkn2 %x=%d\n", pt_tail->iunkn2, pt_tail->iunkn2);\r
+       printf("iunkn3 %x=%d\n", pt_tail->iunkn3, pt_tail->iunkn3);\r
+       printf("road_id %x=%d\n", pt_tail->road_id, pt_tail->road_id);\r
+       printf("dist_along_rd_frac %lf \n",  pt_tail->dist_along_rd_frac);\r
+\r
+       printf("rd_arrive_sc_lat %d gives lat %f\n", \r
+                       pt_tail->rd_arrive_sc_lat, scaled2deg(pt_tail->rd_arrive_sc_lat));\r
+\r
+       printf("rd_arrive_sc_lon %d gives lat %f\n", \r
+                       pt_tail->rd_arrive_sc_lon, scaled2deg(pt_tail->rd_arrive_sc_lon));\r
+\r
+       printf("rd_depart_sc_lat %d gives lat %f\n", \r
+                       pt_tail->rd_depart_sc_lat, scaled2deg(pt_tail->rd_depart_sc_lat));\r
+\r
+       printf("rd_depart_sc_lon %d gives lat %f\n", \r
+                       pt_tail->rd_depart_sc_lon, scaled2deg(pt_tail->rd_depart_sc_lon));\r
+\r
+       printf("iunkn8 %x=%d\n", pt_tail->iunkn8, pt_tail->iunkn8);\r
+       printf("iunkn9 %x=%d\n", pt_tail->iunkn9, pt_tail->iunkn9);\r
+       printf("iunkn10 %x=%d\n", pt_tail->iunkn10, pt_tail->iunkn10);\r
+       printf("iunkn11 %x=%d\n", pt_tail->iunkn11, pt_tail->iunkn11);\r
+       printf("iunkn12 %x=%d\n", pt_tail->iunkn12, pt_tail->iunkn12);\r
+       printf("iunkn13 %x=%d\n", pt_tail->iunkn13, pt_tail->iunkn13);\r
+       printf("iunkn14 %x=%d\n", pt_tail->iunkn14, pt_tail->iunkn14);\r
+\r
+       printbuf((char*)pt_tail, sizeof(struct f_jour_pt_tail));\r
+}\r
+\r
+void print_f_jour_opts(struct f_jour_opts * jopts)\r
+{\r
+       printf("struct f_jour_opts:\n");\r
+\r
+       printf("siunkn0 %d\n", jopts->siunkn0);\r
+       printf("funkn0 %f\n", jopts->funkn0);\r
+       printf("toll_rd_pref %lf\n", jopts->toll_rd_pref);\r
+       printf("motorway_pref %lf\n", jopts->motorway_pref);\r
+       printf("major_rd_pref %lf\n", jopts->major_rd_pref);\r
+       printf("minor_rd_pref %lf\n", jopts->minor_rd_pref);\r
+       printf("ferry_pref %lf\n", jopts->ferry_pref);\r
+       printf("iunkn0 %d\n", jopts->iunkn0);\r
+       printf("iunkn1 %d\n", jopts->iunkn1);\r
+       printf("iunkn2 %d\n", jopts->iunkn2);\r
+       printf("fuel_price %lf\n", jopts->fuel_price);\r
+       printf("iunkn3 %d\n", jopts->iunkn3);\r
+       printf("fuel_price_unit %d\n", jopts->fuel_price_unit);\r
+       printf("iunkn4 %d\n", jopts->iunkn4);\r
+       printf("tank_capacity %lf\n", jopts->tank_capacity);\r
+       printf("tank_capacity_units %d\n", jopts->tank_capacity_units);\r
+       printf("tank_start_level %lf\n", jopts->tank_start_level);\r
+       printf("tank_warn_level %lf\n", jopts->tank_warn_level);\r
+       printf("iunkn5 %d\n", jopts->iunkn5);\r
+       printf("fuel_use_city %lf\n", jopts->fuel_use_city);\r
+       printf("fuel_use_city_unit %d\n", jopts->fuel_use_city_unit);\r
+       printf("iunkn6 %d\n", jopts->iunkn6);\r
+       printf("fuel_use_mway %lf\n", jopts->fuel_use_mway);\r
+       printf("fuel_use_mway_unit %d\n", jopts->fuel_use_mway_unit);\r
+       printf("iunkn7 %d\n", jopts->iunkn7);\r
+       printf("mway_speed %f\n", jopts->mway_speed);\r
+       printf("mway_speed_unit %d\n", jopts->mway_speed_unit);\r
+       printf("iunkn9 %d\n", jopts->iunkn9);\r
+       printf("lim_acc_speed %f\n", jopts->lim_acc_speed);\r
+       printf("lim_acc_speed_unit %d\n", jopts->lim_acc_speed_unit);\r
+       printf("iunkn11 %d\n", jopts->iunkn11);\r
+       printf("maj_rd_speed %f\n", jopts->maj_rd_speed);\r
+       printf("maj_rd_speed_unit %d\n", jopts->maj_rd_speed_unit);\r
+       printf("iunkn13 %d\n", jopts->iunkn13);\r
+       printf("min_rd_speed %f\n", jopts->min_rd_speed);\r
+       printf("min_rd_speed_unit %d\n", jopts->min_rd_speed_unit);\r
+       printf("iunkn15 %d\n", jopts->iunkn15);\r
+       printf("street_speed %f\n", jopts->street_speed);\r
+       printf("street_speed_unit %d\n", jopts->street_speed_unit);\r
+       printf("iunkn17 %d\n", jopts->iunkn17);\r
+       printf("iunkn18 %d\n", jopts->iunkn18);\r
+       printf("funkn1 %f\n", jopts->funkn1);\r
+       printf("iunkn19 %d\n", jopts->iunkn19);\r
+       printf("iunkn20 %d\n", jopts->iunkn20);\r
+       printf("iunkn21 %d\n", jopts->iunkn21);\r
+       printf("funkn2 %f\n", jopts->funkn2);\r
+       printf("iunkn22 %d\n", jopts->iunkn22);\r
+       printf("iunkn23 %d\n", jopts->iunkn23);\r
+       printf("iunkn24 %d\n", jopts->iunkn24);\r
+       printf("funkn3 %f\n", jopts->funkn3);\r
+       printf("iunkn25 %d\n", jopts->iunkn25);\r
+       printf("iunkn26 %d\n", jopts->iunkn26);\r
+       printf("iunkn27 %d\n", jopts->iunkn27);\r
+       printf("funkn4 %f\n", jopts->funkn4);\r
+       printf("iunkn28 %d\n", jopts->iunkn28);\r
+       printf("iunkn29 %d\n", jopts->iunkn29);\r
+       printf("iunkn30 %d\n", jopts->iunkn30);\r
+       printf("funkn5 %f\n", jopts->funkn5);\r
+       printf("iunkn31 %d\n", jopts->iunkn31);\r
+       printf("iunkn32 %d\n", jopts->iunkn32);\r
+       printf("iunkn33 %d\n", jopts->iunkn33);\r
+       printf("start_drv_hr %d\n", jopts->start_drv_hr);\r
+       printf("start_drv_min %d\n", jopts->start_drv_min);\r
+       printf("iunkn34 %d\n", jopts->iunkn34);\r
+       printf("end_drv_hr %d\n", jopts->end_drv_hr);\r
+       printf("end_drv_min %d\n", jopts->end_drv_min);\r
+       printf("fuel_warn_flag %d\n", jopts->fuel_warn_flag);\r
+       printf("iunkn35 %d\n", jopts->iunkn35);\r
+       printf("fuel_fixed_rate_flag %d\n", jopts->fuel_fixed_rate_flag);\r
+       printf("iunkn36 %d\n", jopts->iunkn36);\r
+       printf("fuel_cost_dist %d\n", jopts->fuel_cost_dist);\r
+       printf("route_flex_secs %d\n", jopts->route_flex_secs);\r
+       printf("iunkn37 %d\n", jopts->iunkn37);\r
+       printf("rest_flag %d\n", jopts->rest_flag);\r
+       printf("rest_dur_secs %d\n", jopts->rest_dur_secs);\r
+       printf("rest_interval_secs %d\n", jopts->rest_interval_secs);\r
+\r
+       printbuf((char*)jopts, sizeof(struct f_jour_opts));\r
+       printf("\n");\r
+}\r
+\r
+void print_f_jour_opts_EUR_8(struct f_jour_opts_EUR_8 * jopts)\r
+{\r
+       printf("struct f_jour_opts_EUR_8:\n");\r
+\r
+       printf("iunkn38 %d\n", jopts->iunkn38);\r
+       printf("iunkn39 %d\n", jopts->iunkn39);\r
+       printf("iunkn40 %d\n", jopts->iunkn40);\r
+       printf("iunkn41 %d\n", jopts->iunkn41);\r
+       printf("iunkn42 %d\n", jopts->iunkn42);\r
+       printf("siunkn1 %d\n", jopts->siunkn1);\r
+       printf("route_show_tm %d\n", jopts->route_show_tm);\r
+       printf("route_show_dist %d\n", jopts->route_show_dist);\r
+       printf("route_show_inst %d\n", jopts->route_show_inst);\r
+       printf("route_show_for %d\n", jopts->route_show_for);\r
+       printf("route_show_to %d\n", jopts->route_show_to);\r
+       printf("route_show_font_size %d\n", jopts->route_show_font_size);\r
+       printf("iunkn43 %d\n", jopts->iunkn43);\r
+       printf("iunkn44 %d\n", jopts->iunkn44);\r
+       printf("count_avoid_regions %d\n", jopts->count_avoid_regions);\r
+\r
+       printbuf((char*)jopts, sizeof(struct f_jour_opts_EUR_8));\r
+       printf("\n");\r
+}\r
+\r
+void print_f_jour_opts_EUR_10(struct f_jour_opts_EUR_10 * jopts)\r
+{\r
+       printf("struct f_jour_opts_EUR_10:\n");\r
+\r
+       printf("iunkn38 %d\n", jopts->iunkn38);\r
+       printf("iunkn39 %d\n", jopts->iunkn39);\r
+       printf("iunkn40 %d\n", jopts->iunkn40);\r
+       printf("iunkn41 %d\n", jopts->iunkn41);\r
+       printf("iunkn41 %d\n", jopts->iunkn42);\r
+       printf("count_avoid_regions %d\n", jopts->count_avoid_regions);\r
+\r
+       printbuf((char*)jopts, sizeof(struct f_jour_opts_EUR_10));\r
+       printf("\n");\r
+}\r
+\r
+void print_f_jour_opts_USA_8(struct f_jour_opts_USA_8 * jopts)\r
+{\r
+       printf("struct f_jour_opts_USA_8:\n");\r
+\r
+       printf("iunkn38 %d\n", jopts->iunkn38);\r
+       printf("iunkn39 %d\n", jopts->iunkn39);\r
+       printf("iunkn40 %d\n", jopts->iunkn40);\r
+       printf("iunkn41 %d\n", jopts->iunkn41);\r
+       printf("iunkn42 %d\n", jopts->iunkn42);\r
+       printf("siunkn1 %d\n", jopts->siunkn1);\r
+       printf("iunkn43 %d\n", jopts->iunkn43);\r
+       printf("iunkn44 %d\n", jopts->iunkn44);\r
+       printf("iunkn45 %d\n", jopts->iunkn45);\r
+       printf("iunkn46 %d\n", jopts->iunkn46);\r
+       printf("iunkn47 %d\n", jopts->iunkn47);\r
+       printf("iunkn48 %d\n", jopts->iunkn48);\r
+       printf("iunkn49 %d\n", jopts->iunkn49);\r
+       printf("count_avoid_regions %d\n", jopts->count_avoid_regions);\r
+\r
+       printbuf((char*)jopts, sizeof(struct f_jour_opts_USA_8));\r
+       printf("\n");\r
+}\r
+\r
+void print_f_jour_opts_USA_10(struct f_jour_opts_USA_10 * jopts)\r
+{\r
+       printf("struct f_jour_opts_USA_10:\n");\r
+\r
+       printf("iunkn38 %d\n", jopts->iunkn38);\r
+       printf("iunkn39 %d\n", jopts->iunkn39);\r
+       printf("iunkn40 %d\n", jopts->iunkn40);\r
+       printf("iunkn41 %d\n", jopts->iunkn41);\r
+       printf("iunkn42 %d\n", jopts->iunkn42);\r
+       printf("siunkn1 %d\n", jopts->siunkn1);\r
+       printf("iunkn43 %d\n", jopts->iunkn43);\r
+       printf("iunkn44 %d\n", jopts->iunkn44);\r
+       printf("count_avoid_regions %d\n", jopts->count_avoid_regions);\r
+\r
+       printbuf((char*)jopts, sizeof(struct f_jour_opts_USA_10));\r
+       printf("\n");\r
+}\r
+\r
+void print_f_jour_avoid(struct f_jour_avoid * avoid)\r
+{\r
+       struct gpxpt * gpt = gpx_get_point((char*)avoid);\r
+       struct point pt;\r
+       printf("struct f_jour_avoid:\n");\r
+\r
+       printf("x %f\n", avoid->x);\r
+       printf("y %f\n", avoid->y);\r
+       printf("z %f\n", avoid->z);\r
+       printf("iunkn0 %d\n", avoid->iunkn0);\r
+       printf("iunkn1 %d\n", avoid->iunkn1);\r
+       printf("iunkn2 %d\n", avoid->iunkn2);\r
+       printf("iunkn3 %d\n", avoid->iunkn3);\r
+       printf("iunkn4 %d\n", avoid->iunkn4);\r
+       printf("iunkn5 %d\n", avoid->iunkn5);\r
+       printf("annot_num %d\n", avoid->annot_num);\r
+       printf("x,y,z give lat %f and lon %f\n", gpt->lat, gpt->lon);\r
+\r
+       pt = grid2latlon(avoid->iunkn1, avoid->iunkn2);\r
+       printf("iunkn1, lunkn2 as grid, precision give lat %f and lon %f\n", pt.lat, pt.lon);\r
+       pt = grid2latlon(avoid->iunkn2, avoid->iunkn3);\r
+       printf("iunkn2, lunkn3 as grid, precision give lat %f and lon %f\n", pt.lat, pt.lon);\r
+       pt = grid2latlon(avoid->iunkn3, avoid->iunkn4);\r
+       printf("iunkn3, lunkn4 as grid, precision give lat %f and lon %f\n", pt.lat, pt.lon);\r
+\r
+       printbuf((char*)avoid, sizeof(struct f_jour_avoid));\r
+       printf("\n");\r
+}\r
+\r
+void print_f_jour_trailer(struct f_jour_trailer * trailer)\r
+{\r
+       printf("struct f_jour_trailer:\n");\r
+\r
+       printf("iunkn0 %d\n", trailer->iunkn0);\r
+       printf("iunkn1 %d\n", trailer->iunkn1);\r
+\r
+       printbuf((char*)trailer, sizeof(struct f_jour_trailer));\r
+       printf("\n");\r
+}\r
+\r
+void print_annot_rec(struct annot_rec * rec)\r
+{\r
+       int bit_flags = *(int*)(rec->buf + 8);\r
+       char* rec_type = NULL;\r
+\r
+       if (rec->type<4)\r
+               rec_type =annot_type_name[rec->type];\r
+\r
+       printf("Got annotation id %d, of type %s, %d line points",\r
+                       rec->annot_num, rec_type, rec->line_points);\r
+       if(rec->text !=NULL)\r
+               printf(" and text '%s'", rec->text);\r
+       printf("\n");\r
+       if (opts.verbose_flag > 4)\r
+               printf("(type=%d) text length %d, bitflags %#x buf length %d\n",\r
+                               rec->type, rec->text_length, bit_flags, rec->length);\r
+}\r
+\r
+void print_annotations(struct annotations * annots)\r
+{\r
+       int i;\r
+       // This is only the main stuff\r
+       printf("Annotations list, version=%d, num_annotations=%d, max_annot_num=%d, stream_length=%d\n",\r
+                  annots->version, annots->num_annotations, \r
+                  annots->max_annot_num, annots->stream_length);\r
+       \r
+       for(i=0; i<annots->num_annotations; i++)\r
+               print_annot_rec(annots->annot_list[i]);\r
+}\r
+\r
+void debug_show_sizes()\r
+{\r
+       printf("sze of struct annot_rec is %d \n", sizeof(struct annot_rec));\r
+       printf("sze of struct annotations is %d \n", sizeof(struct annotations));\r
+       printf("sze of struct dictionary is %d \n", sizeof(struct dictionary));\r
+//     printf("sze of struct FORMATIDOFFSET is %d \n", sizeof(struct FORMATIDOFFSET));\r
+       printf("sze of struct gpx_data is %d \n", sizeof(struct gpx_data));\r
+       printf("sze of struct gpxpt is %d \n", sizeof(struct gpxpt));\r
+       printf("sze of struct gpxrte is %d \n", sizeof(struct gpxrte));\r
+       printf("sze of struct gpxtrk is %d \n", sizeof(struct gpxtrk));\r
+       printf("sze of struct jour_header is %d \n", sizeof(struct f_jour_header));\r
+       printf("sze of struct jour_pt_head is %d \n", sizeof(struct f_jour_pt_head));\r
+       printf("sze of struct jour_pt_mid is %d \n", sizeof(struct f_jour_pt_mid));\r
+       printf("sze of struct jour_pt_tail is %d \n", sizeof(struct f_jour_pt_tail));\r
+       printf("sze of struct jour_rtept_rec is %d \n", sizeof(struct jour_rtept));\r
+//     printf("sze of struct jour_trailer_EUR_8 is %d \n", sizeof(struct jour_opts_EUR_8));\r
+       printf("sze of struct jour_trailer_EUR_8 is %d \n", sizeof(struct f_jour_avoid));\r
+//     printf("sze of struct jour_trailer_EUR_8 is %d \n", sizeof(struct jour_trailer_EUR_8));\r
+\r
+       debug_pause();\r
+\r
+       printf("sze of struct journey is %d \n", sizeof(struct journey));\r
+       printf("sze of struct grid_point is %d \n", sizeof(struct grid_point));\r
+       printf("sze of struct ole_property is %d \n", sizeof(struct ole_property));\r
+       printf("sze of struct ole_property_set is %d \n", sizeof(struct ole_property_set));\r
+       printf("sze of struct option is %d \n", sizeof(struct option));\r
+       printf("sze of struct point is %d \n", sizeof(struct point));\r
+//     printf("sze of struct PROPERTYIDOFFSET is %d \n", sizeof(struct PROPERTYIDOFFSET));\r
+//     printf("sze of struct PROPERTYSETHEADER is %d \n", sizeof(struct PROPERTYSETHEADER));\r
+       printf("sze of struct pushpin is %d \n", sizeof(struct pushpin));\r
+       printf("sze of struct pushpin_safelist is %d \n", sizeof(struct pushpin_safelist));\r
+       printf("sze of struct pushpinset is %d \n", sizeof(struct pushpinset));\r
+//     printf("sze of struct SERIALIZEDPROPERTYVALUE is %d \n", sizeof(struct SERIALIZEDPROPERTYVALUE));\r
+       printf("sze of struct st2gpx_options is %d \n", sizeof(struct st2gpx_options));\r
+//     printf("sze of struct tagPROPERTYSECTIONHEADER is %d \n", sizeof(struct tagPROPERTYSECTIONHEADER));\r
+}\r
diff --git a/st2gpx/src/gpx.h b/st2gpx/src/gpx.h
new file mode 100644 (file)
index 0000000..107ddb6
--- /dev/null
@@ -0,0 +1,109 @@
+/*\r
+       gpx.h\r
+\r
+       Extract data from MS Streets & Trips .est and Autoroute .axe files in GPX format.\r
+\r
+    Copyright (C) 2003 James Sherring, james_sherring@yahoo.com\r
+\r
+    This program is free software; you can redistribute it and/or modify\r
+    it under the terms of the GNU General Public License as published by\r
+    the Free Software Foundation; either version 2 of the License, or\r
+    (at your option) any later version.\r
+\r
+    This program is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+\r
+    You should have received a copy of the GNU General Public License\r
+    along with this program; if not, write to the Free Software\r
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA\r
+\r
+\r
+       This app depends on istorage & istorage-make from Pabs (pabs3@zip.to)\r
+       and James Clark's Expat xml parser from http://www.libexpat.org/.\r
+\r
+*/\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+#define GPX_ELEM_TYPE_WPT      1\r
+#define GPX_ELEM_TYPE_RTE      2\r
+#define GPX_ELEM_TYPE_RTEPT    3\r
+#define GPX_ELEM_TYPE_TRK      4\r
+#define GPX_ELEM_TYPE_TRKSEG   5\r
+#define GPX_ELEM_TYPE_TRKPT    6\r
+\r
+#define GPX_ELEM_TYPE_NAME     7\r
+#define GPX_ELEM_TYPE_DESC     8\r
+#define GPX_ELEM_TYPE_SRC      9\r
+\r
+typedef struct gpxpt\r
+{\r
+       double lat;\r
+       double lon;\r
+       double elevation;\r
+       char use_elevation;\r
+       char * name;\r
+       char * desc;\r
+       // more later\r
+} tag_gpxpt;\r
+\r
+struct gpxpt * gpxpt_new();\r
+void gpxpt_delete(struct gpxpt * pt);\r
+struct gpxpt * gpxpt_copy(struct gpxpt * otherpt);\r
+\r
+typedef struct gpxrte\r
+{\r
+       char*   name;\r
+       struct gpxpt**  rtept_list;\r
+       int rtept_list_count;\r
+} tag_gpxrte;\r
+\r
+struct gpxrte * gpxrte_new();\r
+void gpxrte_delete(struct gpxrte * rte);\r
+\r
+typedef struct gpxtrk\r
+{\r
+       struct gpxpt**  trkpt_list;\r
+       int trkpt_list_count;\r
+} tag_gpxtrk;\r
+\r
+struct gpxtrk * gpxtrk_new();\r
+void gpxtrk_delete(struct gpxtrk * trk);\r
+\r
+typedef struct gpx_data\r
+{\r
+       char* data_source_name;\r
+       struct gpxpt ** wpt_list;\r
+       int wpt_list_count;\r
+       struct gpxrte ** rte_list;\r
+       int rte_list_count;\r
+       struct gpxtrk ** trk_list;\r
+       int trk_list_count;\r
+} tag_gpx_data;\r
+\r
+struct gpx_data * gpx_data_new();\r
+void gpx_data_delete(struct gpx_data * data);\r
+\r
+struct gpxpt * find_matching_wpt(struct gpx_data * dat, char* name);\r
+\r
+struct gpx_data * process_gpx_in_file(char* gpx_in_file_name);\r
+void print_gpx_data(struct gpx_data * all_data);\r
+\r
+// FIXME is this the correct way to forward define these?\r
+#ifndef        __cplusplus\r
+extern struct pushpin_safelist;\r
+extern struct journey;\r
+extern struct annotations;\r
+#endif // __cplusplus\r
+                                  \r
+void gpx_write_all(char* gpx_out_file_name, \r
+                                  struct pushpin_safelist *ppplist, \r
+                                  struct journey * jour,\r
+                                  struct annotations * annots);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
diff --git a/st2gpx/src/history.txt b/st2gpx/src/history.txt
new file mode 100644 (file)
index 0000000..d5e0eb6
--- /dev/null
@@ -0,0 +1,31 @@
+History:\r
+\r
+This app started out as ansi C using gcc as an app to explore the .axe file format,\r
+and with the intention of fitting into the GPSBabel ansi C requirement. \r
+\r
+The pushpin data (UserData) required MS Jet libraries, initially this was done\r
+with ADO in VB, then in C++ using MS #import. Note that the ADO type libraries \r
+do not support C via #import, and I was not game to even try direct OLE access to the\r
+ADO libraries via COM. \r
+\r
+So now there is an ugly mix of C/C++ in an app that grew organically rather than being designed.\r
+It probably could be implemented a lot cleaner in c++ and with some inteligent use of streams\r
+etc. \r
+\r
+Yeah, ok, I am just an amateur at this...\r
+\r
+18-10-2003  look mum! I can open an axe files into OLE storage streams using various tools.\r
+21-10-2003     annotations stream dump\r
+27-10-2003     journey & pushpins export using VB module\r
+ 8-11-2003     match journey route-points to pushpins,\r
+                       integrate parts into single C/C++ exe (except istorage)\r
+ 9-11-2003  fixed invalid gpx.\r
+10-11-2003  gpx import working for routes/tracks to s&t annotation lines.\r
+13-11-2003  export as pcx5 for import into Garmin MapSource\r
+20-11-2003     substantial cleanup\r
+                       fixed 8byte alignment in properties.c\r
+                       introduced 1byte alignment for journey analysis\r
+                       understands most journey options\r
+22-11-2003  explores UDM data\r
+28-11-2003     imports pushpins\r
+                       imports lines to v3 annotations (2002+)\r
diff --git a/st2gpx/src/istorage license.txt b/st2gpx/src/istorage license.txt
new file mode 100644 (file)
index 0000000..fde84df
--- /dev/null
@@ -0,0 +1,24 @@
+Copyright (c) 2001, Pabs (pabs3@zip.to)\r
+All rights reserved.\r
+\r
+Redistribution and use in source and binary forms, with or without\r
+modification, are permitted provided that the following conditions\r
+are met:\r
+\r
+Redistributions of source code must retain the above copyright notice,\r
+this list of conditions and the following disclaimer.\r
+Redistributions in binary form must reproduce the above copyright\r
+notice, this list of conditions and the following disclaimer in the\r
+documentation and/or other materials provided with the distribution.\r
+\r
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\r
+HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\r
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\r
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
diff --git a/st2gpx/src/istorage-make license.txt b/st2gpx/src/istorage-make license.txt
new file mode 100644 (file)
index 0000000..5ee1421
--- /dev/null
@@ -0,0 +1,24 @@
+Copyright (c) 2002, Pabs (pabs3@zip.to)\r
+All rights reserved.\r
+\r
+Redistribution and use in source and binary forms, with or without\r
+modification, are permitted provided that the following conditions\r
+are met:\r
+\r
+Redistributions of source code must retain the above copyright notice,\r
+this list of conditions and the following disclaimer.\r
+Redistributions in binary form must reproduce the above copyright\r
+notice, this list of conditions and the following disclaimer in the\r
+documentation and/or other materials provided with the distribution.\r
+\r
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\r
+HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\r
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\r
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
diff --git a/st2gpx/src/journey.c b/st2gpx/src/journey.c
new file mode 100644 (file)
index 0000000..e8fa65e
--- /dev/null
@@ -0,0 +1,464 @@
+/*\r
+       journey.c\r
+\r
+       Extract data from MS Streets & Trips .est and Autoroute .axe files in GPX format.\r
+\r
+    Copyright (C) 2003 James Sherring, james_sherring@yahoo.com\r
+\r
+    This program is free software; you can redistribute it and/or modify\r
+    it under the terms of the GNU General Public License as published by\r
+    the Free Software Foundation; either version 2 of the License, or\r
+    (at your option) any later version.\r
+\r
+    This program is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+\r
+    You should have received a copy of the GNU General Public License\r
+    along with this program; if not, write to the Free Software\r
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA\r
+\r
+\r
+       This app depends on istorage & istorage-make from Pabs (pabs3@zip.to)\r
+       and James Clark's Expat xml parser from http://www.libexpat.org/.\r
+\r
+*/\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <malloc.h>\r
+#include <memory.h>\r
+#include <math.h>\r
+#include <string.h>\r
+\r
+#include "gpx.h"\r
+#include "st2gpx.h"\r
+#include "pushpins.h"\r
+#include "ppinutil.h"\r
+\r
+#include "journey.h"\r
+\r
+float scaled2deg(int scaled_deg)\r
+// there must be a simple single line calc\r
+{\r
+       double x=scaled_deg;\r
+       x = x*360/0x10000;\r
+       x = x/0x10000;\r
+       return (float)x;\r
+}\r
+\r
+void jour_rtept_init(struct jour_rtept * nw)\r
+{\r
+//     struct jour_rtept_rec * nw=(struct jour_rtept_rec*)xmalloc(sizeof(struct jour_rtept_rec));\r
+       nw->pthead_os=0;\r
+       nw->text1=NULL;\r
+       nw->ptmid_os=0;\r
+       nw->text2=NULL;\r
+       nw->pttail_os=0;\r
+       // pointer to pushpin owned by pushpinlist\r
+       nw->pushpin=NULL;\r
+       strcpy(nw->garmin_ident,"      ");\r
+}\r
+\r
+void jour_rtept_delete(struct jour_rtept * jourpt)\r
+{\r
+       if (jourpt==NULL)\r
+               return;\r
+       xfree(jourpt->text1);\r
+       xfree(jourpt->text2);\r
+       // This is part of an array, so free the array\r
+       //xfree(jourpt);\r
+}\r
+\r
+struct journey * journey_new()\r
+{\r
+       struct journey * nw = (struct journey*)xmalloc(sizeof(struct journey));\r
+       nw->buf_len=0;\r
+       nw->buf=NULL;\r
+\r
+       nw->rtept_list=NULL;\r
+       nw->jopts_os=0;\r
+       nw->jopts_eur8_os=0;\r
+       nw->jopts_usa8_os=0;\r
+       nw->jopts_usa10_os=0;\r
+       nw->avoid_os_list=NULL;\r
+       nw->trailer_os=0;\r
+       return nw;\r
+}\r
+\r
+void journey_delete(struct journey * jour)\r
+{\r
+       int i;\r
+       if (jour==NULL)\r
+               return;\r
+       for(i=0; i< jour->count_rtepts; i++)\r
+               jour_rtept_delete(jour->rtept_list + i);\r
+       xfree(jour->rtept_list);\r
+       xfree(jour->avoid_os_list);\r
+       xfree(jour->buf);\r
+       xfree(jour);\r
+}\r
+\r
+\r
+struct journey * process_journey_stream (char* jour_in_file_name, \r
+                                                                                struct pushpin_safelist * ppplist)\r
+{\r
+       int j;\r
+       int readbyte;\r
+       int bytes2read=0;\r
+\r
+       int max_read_more = 10000;\r
+       int readmore=0;\r
+       int status;\r
+       char readmorebuf[10000];\r
+\r
+       int UdId;\r
+//     double lat;\r
+//     double lon;\r
+//     double x;\r
+//     double y;\r
+//     double z;\r
+\r
+       struct journey * jour = journey_new();\r
+//     struct jour_rtept * thispt=NULL;\r
+       FILE* jour_in_file=NULL;\r
+       struct f_jour_pt_head * pt_head=NULL;\r
+       struct f_jour_opts_EUR_8* opts_eur8;\r
+       struct f_jour_opts_EUR_10* opts_eur10;\r
+       struct f_jour_opts_USA_8* opts_usa8;\r
+       struct f_jour_opts_USA_10* opts_usa10;\r
+\r
+       printf("Processing Journey stream\n");\r
+\r
+       if ((jour_in_file = fopen(jour_in_file_name, "rb")) == NULL)\r
+       {\r
+               fprintf(stderr, "Quitting because I cannot open %s\n", jour_in_file_name);\r
+               exit(1);\r
+       }\r
+       \r
+       bytes2read=sizeof(struct f_jour_header);\r
+       jour->buf=(char*)xmalloc(jour->buf_len+bytes2read);\r
+       status = readbytes(jour_in_file, jour->buf, bytes2read);\r
+       jour->buf_len += bytes2read;\r
+       if (status!=bytes2read)\r
+       {\r
+               printf("Unexpected EOF in the Journey stream header\n");\r
+           fclose(jour_in_file);\r
+               return jour;\r
+       }\r
+       jour->header_os = 0;\r
+       jour->count_rtepts = ((struct f_jour_header*)(jour->buf + jour->header_os))->cpoints;\r
+\r
+       printf("got Journey file header with %d waypoints\n", jour->count_rtepts);\r
+       debug_pause();\r
+       if (opts.explore_flag)\r
+               print_f_jour_header((struct f_jour_header*)(jour->buf + jour->header_os));\r
+\r
+       // an array of jour_rtept\r
+       jour->rtept_list = (struct jour_rtept *)xmalloc(\r
+                                               jour->count_rtepts*sizeof(struct jour_rtept));\r
+\r
+       for (j=0; j< jour->count_rtepts; j++)\r
+       {\r
+               jour_rtept_init(jour->rtept_list + j);\r
+\r
+               // read pt header\r
+               bytes2read=sizeof(struct f_jour_pt_head);\r
+               jour->buf=(char*)xrealloc(jour->buf, jour->buf_len+bytes2read);\r
+               status = readbytes(jour_in_file, jour->buf + jour->buf_len, bytes2read);\r
+               if (status!=bytes2read)\r
+               {\r
+                       printf("Unexpected EOF in the Journey stream, routepoint %d\n", j);\r
+                   fclose(jour_in_file);\r
+                       return jour;\r
+               }\r
+               jour->rtept_list[j].pthead_os=jour->buf_len;\r
+               jour->buf_len += bytes2read;\r
+               if (opts.explore_flag)\r
+                       print_f_jour_pt_head((struct f_jour_pt_head*)\r
+                                                                       (jour->buf + jour->rtept_list[j].pthead_os));\r
+\r
+               // read pt text1\r
+               bytes2read=((struct f_jour_pt_head*)\r
+                                               (jour->buf + jour->rtept_list[j].pthead_os))->cbtext1;\r
+               if (bytes2read)\r
+               {\r
+                       jour->buf=(char*)xrealloc(jour->buf, jour->buf_len+bytes2read);\r
+                       status = readbytes(jour_in_file, jour->buf + jour->buf_len, bytes2read);\r
+                       if (status!=bytes2read)\r
+                       {\r
+                               printf("Unexpected EOF in the Journey stream, routepoint %d\n", j);\r
+                           fclose(jour_in_file);\r
+                               return jour;\r
+                       }\r
+                       jour->rtept_list[j].text1= (char*)malloc(bytes2read+1);\r
+                       memcpy(jour->rtept_list[j].text1, jour->buf + jour->buf_len, bytes2read);\r
+                       jour->rtept_list[j].text1[bytes2read]=0;\r
+                       jour->buf_len += bytes2read;\r
+               \r
+                       str2ascii(jour->rtept_list[j].text1);\r
+               }\r
+               if (opts.explore_flag)\r
+                       printf("Got text1 %s\n", jour->rtept_list[j].text1);\r
+\r
+               // read pt middle\r
+               bytes2read=sizeof(struct f_jour_pt_mid);\r
+               jour->buf=(char*)xrealloc(jour->buf, jour->buf_len+bytes2read);\r
+               status = readbytes(jour_in_file, jour->buf + jour->buf_len, bytes2read);\r
+               if (status!=bytes2read)\r
+               {\r
+                       printf("Unexpected EOF in the Journey stream, routepoint %d\n", j);\r
+                   fclose(jour_in_file);\r
+                       return jour;\r
+               }\r
+               jour->rtept_list[j].ptmid_os=jour->buf_len;\r
+               jour->buf_len += bytes2read;\r
+               if (opts.explore_flag)\r
+               {\r
+                       printf("dumping jour->rtept_list[%d].ptmid:\n", j);\r
+                       printbuf(jour->buf + jour->rtept_list[j].ptmid_os, bytes2read);\r
+               }\r
+\r
+               // read pt text2\r
+               bytes2read=2*(((struct f_jour_pt_mid*)(jour->buf+jour->rtept_list[j].ptmid_os))->cbtext2);\r
+               if (bytes2read)\r
+               {\r
+               jour->buf=(char*)xrealloc(jour->buf, jour->buf_len+bytes2read);\r
+                       status = readbytes(jour_in_file, jour->buf + jour->buf_len, bytes2read);\r
+                       if (status!=bytes2read)\r
+                       {\r
+                               printf("Unexpected EOF in the Journey stream, routepoint %d\n", j);\r
+                           fclose(jour_in_file);\r
+                               return jour;\r
+                       }\r
+                       jour->rtept_list[j].text2= (char*)malloc(bytes2read+2);\r
+                       memcpy(jour->rtept_list[j].text2, jour->buf + jour->buf_len, bytes2read);\r
+                       jour->rtept_list[j].text2[bytes2read]=0;\r
+                       jour->rtept_list[j].text2[bytes2read+1]=0;\r
+                       jour->buf_len += bytes2read;\r
+               }\r
+               if (opts.explore_flag)\r
+                       wprintf(L"Got text2 %s\n", jour->rtept_list[j].text2);\r
+\r
+               // read pt tail\r
+               bytes2read=sizeof(struct f_jour_pt_tail);\r
+               jour->buf=(char*)xrealloc(jour->buf, jour->buf_len+bytes2read);\r
+               status = readbytes(jour_in_file, jour->buf + jour->buf_len, bytes2read);\r
+               if (status!=bytes2read)\r
+               {\r
+                       printf("Unexpected EOF in the Journey stream, routepoint %d\n", j);\r
+                   fclose(jour_in_file);\r
+                       return jour;\r
+               }\r
+               jour->rtept_list[j].pttail_os=jour->buf_len;\r
+               jour->buf_len += bytes2read;\r
+               if (opts.explore_flag)\r
+                       print_f_jour_pt_tail((struct f_jour_pt_tail*)(jour->buf +jour->rtept_list[j].pttail_os));\r
+\r
+               pt_head = (struct f_jour_pt_head*)(jour->buf+jour->rtept_list[j].pthead_os);\r
+//             UdId= ((struct f_jour_pt_head*)(jour->buf+jour->rtept_list[j].pthead_os))->UdId;\r
+               UdId = pt_head->UdId;\r
+               jour->rtept_list[j].pushpin = ppin_by_UdId(UdId, ppplist);\r
+\r
+               if (jour->rtept_list[j].pushpin != NULL)\r
+               {\r
+                       if (opts.verbose_flag > 5)\r
+                       {\r
+                               printf("Found matching pushpin:\n");\r
+                               printf("Pushpin name is: %s\n", jour->rtept_list[j].pushpin->UdName);\r
+                               printf("Pushpin short note is: %s\n", jour->rtept_list[j].pushpin->NoteShort);\r
+                       }\r
+/*                     if (opts.verbose_flag > 4)\r
+                       {\r
+                               lat=jour->rtept_list[j].pushpin->lat;\r
+                               lon=jour->rtept_list[j].pushpin->lon;\r
+\r
+                               printf("Matching pushpin Grid %#x=%d, Precision %#x=%d, MOBBId %#x=%d\n", \r
+                                               jour->rtept_list[j].pushpin->Grid, \r
+                                               jour->rtept_list[j].pushpin->Grid, \r
+                                               jour->rtept_list[j].pushpin->Precision, \r
+                                               jour->rtept_list[j].pushpin->Precision, \r
+                                               jour->rtept_list[j].pushpin->MOBBId, \r
+                                               jour->rtept_list[j].pushpin->MOBBId);\r
+\r
+                               printf("Matching pushpin Lat %f Lon %f\n", \r
+                                               jour->rtept_list[j].pushpin->lat, \r
+                                               jour->rtept_list[j].pushpin->lon);\r
+\r
+                               x = cos(lon*M_PI/180)*cos(lat*M_PI/180);\r
+                               y = sin(lon*M_PI/180)*cos(lat*M_PI/180);\r
+                               z = sin(lat*M_PI/180);\r
+\r
+                               printf("For matching pushpin X=%f Y=%f Z=%f\n", x,y,z); \r
+                       }\r
+*/\r
+               }\r
+/*             else\r
+               {\r
+                       printf("*** Warning *** Ignoring route point '%s' without matching pushpin\n",\r
+                                       jour->rtept_list[j].text1);\r
+                       printf("(yes, I should do someting more clever than this).\n");\r
+                       if (UdId)\r
+                               printf("There should have been a matching pushin because UdId=%d\n", UdId);\r
+               }\r
+*/\r
+       }\r
+\r
+       // read jour generic opts\r
+       bytes2read=sizeof(struct f_jour_opts);\r
+       jour->buf=(char*)xrealloc(jour->buf, jour->buf_len+bytes2read);\r
+       status = readbytes(jour_in_file, jour->buf + jour->buf_len, bytes2read);\r
+       if (status!=bytes2read)\r
+       {\r
+               printf("Unexpected EOF in the Journey stream, options\n");\r
+           fclose(jour_in_file);\r
+               return jour;\r
+       }\r
+       jour->jopts_os=jour->buf_len;\r
+       jour->buf_len += bytes2read;\r
+       if (opts.explore_flag)\r
+               print_f_jour_opts((struct f_jour_opts*)(jour->buf + jour->jopts_os));\r
+\r
+       // read file-version specific journey options\r
+       if( (opts.st_version_num==8) && (opts.isUSA==0))\r
+       {\r
+               bytes2read=sizeof(struct f_jour_opts_EUR_8);\r
+               jour->buf=(char*)xrealloc(jour->buf, jour->buf_len+bytes2read);\r
+               status = readbytes(jour_in_file, jour->buf + jour->buf_len, bytes2read);\r
+               if (status!=bytes2read)\r
+               {\r
+                       printf("Unexpected EOF in the Journey stream, options eur8\n");\r
+                   fclose(jour_in_file);\r
+                       return jour;\r
+               }\r
+               jour->jopts_eur8_os=jour->buf_len;\r
+               jour->buf_len += bytes2read;\r
+               opts_eur8=(struct f_jour_opts_EUR_8*)(jour->buf + jour->jopts_eur8_os);\r
+               jour->count_avoid_regions = opts_eur8->count_avoid_regions;\r
+               if (opts.explore_flag)\r
+                       print_f_jour_opts_EUR_8(opts_eur8);\r
+       }\r
+       else if(    ( (opts.st_version_num==10) && (opts.isUSA==0) )\r
+                        || ( (opts.st_version_num==9)  && (opts.isUSA==1) )\r
+                        || ( (opts.st_version_num==11) && (opts.isUSA==1) ))\r
+       {\r
+               bytes2read=sizeof(struct f_jour_opts_EUR_10);\r
+               jour->buf=(char*)xrealloc(jour->buf, jour->buf_len+bytes2read);\r
+               status = readbytes(jour_in_file, jour->buf + jour->buf_len, bytes2read);\r
+               if (status!=bytes2read)\r
+               {                       \r
+                       printf("Unexpected EOF in the Journey stream, options eur10\n");\r
+                   fclose(jour_in_file);\r
+                       return jour;\r
+               }\r
+               jour->jopts_eur10_os=jour->buf_len;\r
+               jour->buf_len += bytes2read;\r
+               opts_eur10=(struct f_jour_opts_EUR_10*)(jour->buf + jour->jopts_eur10_os);\r
+               jour->count_avoid_regions = opts_eur10->count_avoid_regions;\r
+               if (opts.explore_flag)\r
+                       print_f_jour_opts_EUR_10(opts_eur10);\r
+       }\r
+       else if( (opts.st_version_num==8) && (opts.isUSA) )\r
+       {\r
+               bytes2read=sizeof(struct f_jour_opts_USA_8);\r
+               jour->buf=(char*)xrealloc(jour->buf, jour->buf_len+bytes2read);\r
+               status = readbytes(jour_in_file, jour->buf + jour->buf_len, bytes2read);\r
+               if (status!=bytes2read)\r
+               {\r
+                       printf("Unexpected EOF in the Journey stream, options usa8\n");\r
+                   fclose(jour_in_file);\r
+                       return jour;\r
+               }\r
+               jour->jopts_usa8_os=jour->buf_len;\r
+               jour->buf_len += bytes2read;\r
+               opts_usa8=(struct f_jour_opts_USA_8*)(jour->buf + jour->jopts_usa8_os);\r
+               jour->count_avoid_regions = opts_usa8->count_avoid_regions;\r
+               if (opts.explore_flag)\r
+                       print_f_jour_opts_USA_8(opts_usa8);\r
+       }\r
+       else if( (opts.st_version_num==10) && (opts.isUSA) )\r
+       {\r
+               bytes2read=sizeof(struct f_jour_opts_USA_10);\r
+               jour->buf=(char*)xrealloc(jour->buf, jour->buf_len+bytes2read);\r
+               status = readbytes(jour_in_file, jour->buf + jour->buf_len, bytes2read);\r
+               if (status!=bytes2read)\r
+               {\r
+                       printf("Unexpected EOF in the Journey stream, options usa10\n");\r
+                   fclose(jour_in_file);\r
+                       return jour;\r
+               }\r
+               jour->jopts_usa10_os=jour->buf_len;\r
+               jour->buf_len += bytes2read;\r
+               opts_usa10=(struct f_jour_opts_USA_10*)(jour->buf + jour->jopts_usa10_os);\r
+               jour->count_avoid_regions = opts_usa10->count_avoid_regions;\r
+               if (opts.explore_flag)\r
+                       print_f_jour_opts_USA_10(opts_usa10);\r
+       }\r
+       else\r
+               printf("I dont yet understand the structure of the Journey options for this file version.\n");\r
+\r
+       if (jour->count_avoid_regions >0)\r
+       {\r
+               printf("Reading %d avoid regions", jour->count_avoid_regions);\r
+\r
+               // an array of pointers to f_jour_avoid\r
+               jour->avoid_os_list=(int*)xmalloc((jour->count_avoid_regions)*sizeof(int));\r
+\r
+               for (j=0; j< jour->count_avoid_regions; j++)\r
+               {\r
+                       // read avoid record\r
+                       bytes2read=sizeof(struct f_jour_avoid);\r
+                       jour->buf=(char*)xrealloc(jour->buf, jour->buf_len+bytes2read);\r
+                       status = readbytes(jour_in_file, jour->buf + jour->buf_len, bytes2read);\r
+                       if (status!=bytes2read)\r
+                       {\r
+                               printf("Unexpected EOF in the Journey stream, avoid record %d\n", j);\r
+                               fclose(jour_in_file);\r
+                               return jour;\r
+                       }\r
+                       jour->avoid_os_list[j]= jour->buf_len;\r
+                       jour->buf_len += bytes2read;\r
+                       if (opts.explore_flag)\r
+                               print_f_jour_avoid((struct f_jour_avoid*)(jour->buf + jour->avoid_os_list[j]));\r
+               }\r
+       }\r
+\r
+       // read journey tail\r
+       bytes2read=sizeof(struct f_jour_trailer);\r
+       jour->buf=(char*)xrealloc(jour->buf, jour->buf_len+bytes2read);\r
+       status = readbytes(jour_in_file, jour->buf + jour->buf_len, bytes2read);\r
+       if (status!=bytes2read)\r
+       {\r
+               printf("Unexpected EOF in the Journey stream, trailer\n");\r
+           fclose(jour_in_file);\r
+               return jour;\r
+       }\r
+       jour->trailer_os=jour->buf_len;\r
+       jour->buf_len += bytes2read;\r
+       if (opts.explore_flag)\r
+               print_f_jour_trailer((struct f_jour_trailer*)(jour->buf + jour->trailer_os));\r
+\r
+       readmore=0;\r
+       if ((readbyte = getc(jour_in_file))!=EOF)\r
+       {\r
+               fprintf (stderr, "Did not finish reading journey file at EOF\n");\r
+\r
+               do {\r
+                       readmorebuf[readmore]=(char)readbyte;\r
+                       readmore++;\r
+                       if (readmore>max_read_more)\r
+                               break;\r
+               } while ((readbyte = getc(jour_in_file))!=EOF);\r
+\r
+               printf("read a further %d bytes past expected eof\n", readmore);\r
+               printbuf(readmorebuf, readmore);\r
+       }\r
+\r
+    fclose(jour_in_file);\r
+\r
+       printf("Finished processing Journey stream.\n");\r
+       fflush(stdout);\r
+\r
+       return jour;\r
+}\r
diff --git a/st2gpx/src/journey.h b/st2gpx/src/journey.h
new file mode 100644 (file)
index 0000000..0740384
--- /dev/null
@@ -0,0 +1,382 @@
+/*\r
+       journey.h\r
+\r
+       Extract data from MS Streets & Trips .est and Autoroute .axe files in GPX format.\r
+\r
+    Copyright (C) 2003 James Sherring, james_sherring@yahoo.com\r
+\r
+    This program is free software; you can redistribute it and/or modify\r
+    it under the terms of the GNU General Public License as published by\r
+    the Free Software Foundation; either version 2 of the License, or\r
+    (at your option) any later version.\r
+\r
+    This program is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+\r
+    You should have received a copy of the GNU General Public License\r
+    along with this program; if not, write to the Free Software\r
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA\r
+\r
+\r
+       This app depends on istorage & istorage-make from Pabs (pabs3@zip.to)\r
+       and James Clark's Expat xml parser from http://www.libexpat.org/.\r
+\r
+*/\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+#define JOUR_FILE_HEAD_LEN 32\r
+#define JOUR_FILE_TAIL_LEN_EUR_V8 430\r
+#define JOUR_FILE_TAIL_LEN_USA_V8 426\r
+#define JOUR_FILE_TAIL_LEN_USA_V10 396\r
+\r
+// + text1 +2*text2\r
+#define JOUR_WPTREC_LEN 121\r
+\r
+#define JOUR_FILE_OS_NUMREC 16\r
+\r
+#define JOURWPT_REC_HEAD_LEN 41\r
+\r
+#define JOURWPT_RECOS_WPTNUM 0\r
+#define JOURWPT_RECOS_STR1LEN 40\r
+#define JOURWPT_RECOS_STR1 41\r
+// + val(JOURWPT_RECOS_STR1LEN)\r
+#define JOURWPT_RECOS_STR2LEN 44\r
+#define JOURWPT_RECOS_STR2 45\r
+\r
+// Still to test in Journey:\r
+// * points located by address Vs by mouse Vs by pushpin\r
+// * avoid areas\r
+// * drag route\r
+typedef struct f_jour_header\r
+{\r
+       int     iunkn0;\r
+       int     iunkn1;\r
+       int     iunkn2;\r
+       int     iunkn3;\r
+       unsigned int cpoints;\r
+       int     iunkn4;\r
+       int     iunkn5;\r
+       int     iunkn6;\r
+} tag_f_jour_header;\r
+\r
+typedef struct f_jour_pt_head\r
+{\r
+       // DB prim key for pushpin\r
+       // 0 if no pushpin\r
+       int UdId;\r
+       int     stop_dur_secs;\r
+       int     iunkn0;\r
+       int sched_arrive_flag;\r
+       // This may have more meaning,\r
+       // it changes with small changes in route.\r
+       // Perhaps just small changes in route time?\r
+       int     sched_depart_flag;\r
+       int     arrive_time_secs;\r
+       int     depart_time_secs;\r
+       int     iunkn1;\r
+       // The coords for the actual journey point, not neccessarily on a road.\r
+       //ie =lat/360*2^32\r
+       int scaled_lon;\r
+       int scaled_lat;\r
+       unsigned char cbtext1;\r
+} tag_f_jour_pt_head;\r
+\r
+// then jour_pt_head.cbtext1 bytes of text\r
+\r
+typedef struct f_jour_pt_mid\r
+{\r
+       // this just seems to be a const FF FE FF\r
+       char mid_tag[3];\r
+       unsigned char cbtext2;\r
+} tag_f_jour_pt_mid;\r
+\r
+// then 2*jour_pt_mid.cbtext2 bytes of wide text\r
+\r
+typedef struct f_jour_pt_tail\r
+{\r
+       // 0=fastest\r
+       // 1=shortest\r
+       // 2=prefered\r
+       // (from previous jour_pt)\r
+       int     route_rd_pref; // =0\r
+       // these seem const\r
+       int iunkn0; // = 1\r
+       int iunkn1; // = 4\r
+       int iunkn2; // =0\r
+       int iunkn3; // =1\r
+       int road_id;\r
+       double dist_along_rd_frac;\r
+       // The coords for the arrival point on the road\r
+       //ie =lat/360*2^32\r
+       int rd_arrive_sc_lat;\r
+       int rd_arrive_sc_lon;\r
+       // The coords for the departure point on the road\r
+       int rd_depart_sc_lat;\r
+       int rd_depart_sc_lon;\r
+       int     iunkn8;  // 4 \r
+       int     iunkn9;  // 1 \r
+       int     iunkn10; // 1 \r
+       int     iunkn11; // 6 \r
+       int     iunkn12; // 1\r
+       int     iunkn13; // 1\r
+       // ? size ?\r
+       int     iunkn14; // 30\r
+} tag_f_jour_pt_tail;\r
+\r
+typedef struct f_jour_opts\r
+{\r
+       // @00\r
+       short int       siunkn0;\r
+       float   funkn0;         \r
+       double  toll_rd_pref;\r
+       double  motorway_pref;  // ok\r
+       // @16\r
+       double  major_rd_pref; \r
+       double  minor_rd_pref;\r
+       // @26\r
+       double  ferry_pref;\r
+       int             iunkn0;\r
+       // @32\r
+       int             iunkn1;\r
+       int             iunkn2;\r
+       double  fuel_price;                     // ok\r
+       // @42\r
+       // 3 = per US Gallon\r
+       int             iunkn3;\r
+       int             fuel_price_unit;\r
+       int             iunkn4;\r
+       double  tank_capacity;          // ok\r
+       // @56\r
+       // 2 = liters\r
+       int             tank_capacity_units;\r
+       double  tank_start_level;       // ok\r
+       // @62\r
+       double  tank_warn_level;        // ok\r
+       int             iunkn5; \r
+       double  fuel_use_city;          // ok\r
+       // @76\r
+       // 3 = liters/100k\r
+       int             fuel_use_city_unit;\r
+       int             iunkn6;\r
+       double  fuel_use_mway;          //ok\r
+       // @86\r
+       // 3 = liters/100k\r
+       int             fuel_use_mway_unit;\r
+       int             iunkn7;\r
+       double  mway_speed;                     //ok\r
+       // @96\r
+       int             mway_speed_unit;\r
+       int             iunkn9;\r
+       double  lim_acc_speed;          //ok\r
+       // @a6\r
+       int             lim_acc_speed_unit;\r
+       int             iunkn11;\r
+       double  maj_rd_speed;           //ok\r
+       // @b6\r
+       int             maj_rd_speed_unit;\r
+       int             iunkn13;\r
+       double  min_rd_speed;           //ok\r
+       // @c6\r
+       int             min_rd_speed_unit;\r
+       int             iunkn15;\r
+       double  street_speed;           //ok\r
+       // @d6\r
+       int             street_speed_unit;\r
+       int             iunkn17;\r
+       int             iunkn18;\r
+       float   funkn1;\r
+       // @e6\r
+       int             iunkn19;\r
+       int             iunkn20;\r
+       int             iunkn21;\r
+       float   funkn2;\r
+       // @f6\r
+       int             iunkn22;\r
+       int             iunkn23;\r
+       int             iunkn24;\r
+       float   funkn3;\r
+       // @106\r
+       int             iunkn25;\r
+       int             iunkn26;\r
+       int             iunkn27;\r
+       float   funkn4;\r
+       // @116\r
+       int             iunkn28;\r
+       int             iunkn29;\r
+       int             iunkn30;\r
+       float   funkn5;\r
+       // @126\r
+       int             iunkn31;\r
+       int             iunkn32;\r
+       int             iunkn33;\r
+       int             start_drv_hr;           //ok\r
+       // @136\r
+       int             start_drv_min;          //ok\r
+       int             iunkn34;\r
+       int             end_drv_hr;                     //ok\r
+       int             end_drv_min;            //ok\r
+       // @146\r
+       int             fuel_warn_flag;         \r
+       int             iunkn35;\r
+       int             fuel_fixed_rate_flag;\r
+       int             iunkn36;\r
+       // @156\r
+       int             fuel_cost_dist; \r
+       int             route_flex_secs;        //ok\r
+       int             iunkn37;\r
+       int             rest_flag;\r
+       // @166\r
+       int             rest_dur_secs;\r
+       int             rest_interval_secs;\r
+} tag_jour_opts;\r
+\r
+typedef struct f_jour_opts_EUR_8\r
+{\r
+       int             iunkn38;\r
+       int             iunkn39;\r
+       // @176\r
+       int             iunkn40;\r
+       int             iunkn41;\r
+       int             iunkn42;\r
+       short int       siunkn1;\r
+       // @184\r
+       int             route_show_tm;\r
+       int             route_show_dist;\r
+       int             route_show_inst;\r
+       // @190\r
+       int             route_show_for;\r
+       int             route_show_to;\r
+       int             route_show_font_size;\r
+       int             iunkn43;\r
+       // @1a0\r
+       // not in usa version8\r
+       int             iunkn44;\r
+       unsigned short int count_avoid_regions;\r
+} tag_f_jour_opts_EUR_8;\r
+\r
+// Also works for USA9 and USA11\r
+typedef struct f_jour_opts_EUR_10\r
+{\r
+       int             iunkn38;\r
+       int             iunkn39;\r
+       // @176\r
+       int             iunkn40;\r
+       int             iunkn41;\r
+       int             iunkn42;\r
+\r
+       unsigned short int count_avoid_regions;\r
+} tag_f_jour_opts_EUR_10;\r
+\r
+typedef struct f_jour_opts_USA_8\r
+{\r
+       int             iunkn38;\r
+       int             iunkn39;\r
+       // @176\r
+       int             iunkn40;\r
+       int             iunkn41;\r
+       int             iunkn42;\r
+       short int       siunkn1;\r
+       // @184\r
+       int             iunkn43;\r
+       int             iunkn44;\r
+       int             iunkn45;\r
+       // @190\r
+       int             iunkn46;\r
+       int             iunkn47;\r
+       int             iunkn48;\r
+       int             iunkn49;\r
+       // @1a0\r
+       unsigned short int count_avoid_regions;\r
+} tag_f_jour_opts_USA_8;\r
+\r
+typedef struct f_jour_opts_USA_10\r
+{\r
+       int             iunkn38;\r
+       int             iunkn39;\r
+       // @176\r
+       int             iunkn40;\r
+       int             iunkn41;\r
+       int             iunkn42;\r
+       short int       siunkn1;\r
+       // @184\r
+       int             iunkn43;\r
+       int             iunkn44;\r
+       unsigned short int count_avoid_regions;\r
+} tag_f_jour_opts_USA_10;\r
+\r
+\r
+typedef struct f_jour_avoid\r
+{\r
+       float   x;\r
+       float   y;\r
+       float   z;\r
+       int             iunkn0;\r
+       int             iunkn1;\r
+       int             iunkn2;\r
+       int             iunkn3;\r
+       int             iunkn4;\r
+       int             iunkn5;\r
+       // avoid num? annot?\r
+       int             annot_num;\r
+} tag_f_jour_avoid;\r
+\r
+\r
+typedef struct f_jour_trailer\r
+{\r
+       int             iunkn0; // =0x65\r
+       int             iunkn1;\r
+} f_tag_jour_trailer;\r
+\r
+typedef struct jour_rtept\r
+{\r
+       int pthead_os;\r
+       // mem owned by this struct, as buf does not have terminating null\r
+       char* text1;\r
+       int ptmid_os;\r
+       // mem owned by this struct, as buf does not have terminating null\r
+       char* text2;\r
+       int pttail_os;\r
+       // pointer to pushpin owned by pushpinlist\r
+       struct pushpin* pushpin;\r
+       char garmin_ident[7];\r
+} tag_jour_trept;\r
+\r
+struct jour_rtept_rec * jour_rtept_rec_new();\r
+void jour_rtept_rec_delete(struct jour_rtept_rec * jourpt_rec);\r
+\r
+typedef struct journey\r
+{\r
+       int buf_len;\r
+       char* buf;\r
+       // We need to use nasty unsigned shorts if we compare to ->header->cpoints\r
+       int count_rtepts;\r
+       // a convenience for looking in multiple version opts \r
+       int count_avoid_regions;\r
+       int header_os;\r
+       // an array of jour_rtept\r
+       struct jour_rtept * rtept_list;\r
+       int jopts_os;\r
+       int jopts_eur8_os;\r
+       int jopts_eur10_os;\r
+       int jopts_usa8_os;\r
+       int jopts_usa10_os;\r
+       // an array of ofsets to f_jour_avoid\r
+       int * avoid_os_list;\r
+       int trailer_os;\r
+} tag_journey;\r
+\r
+float scaled2deg(int scaled_deg);\r
+\r
+struct journey * journey_new();\r
+void journey_delete(struct journey * jour);\r
+\r
+struct journey * process_journey_stream (char* jour_in_file_name, struct pushpin_safelist * ppplist);\r
+\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
diff --git a/st2gpx/src/msado15.tlh b/st2gpx/src/msado15.tlh
new file mode 100644 (file)
index 0000000..b492464
--- /dev/null
@@ -0,0 +1,2997 @@
+// Created by Microsoft (R) C/C++ Compiler Version 12.00.8168.0 (1f62c7b3).\r
+//\r
+// msado15.tlh\r
+//\r
+// C++ source equivalent of Win32 type library msado15.dll\r
+// compiler-generated file created 11/21/03 at 18:38:05 - DO NOT EDIT!\r
+\r
+#pragma once\r
+#pragma pack(push, 8)\r
+\r
+#include <comdef.h>\r
+\r
+namespace ADODB {\r
+\r
+//\r
+// Forward references and typedefs\r
+//\r
+\r
+typedef enum SearchDirectionEnum SearchDirection;\r
+struct __declspec(uuid("00000512-0000-0010-8000-00aa006d2ea4"))\r
+/* dual interface */ _Collection;\r
+struct __declspec(uuid("00000513-0000-0010-8000-00aa006d2ea4"))\r
+/* dual interface */ _DynaCollection;\r
+struct __declspec(uuid("00000534-0000-0010-8000-00aa006d2ea4"))\r
+/* dual interface */ _ADO;\r
+struct __declspec(uuid("00000504-0000-0010-8000-00aa006d2ea4"))\r
+/* dual interface */ Properties;\r
+struct __declspec(uuid("00000503-0000-0010-8000-00aa006d2ea4"))\r
+/* dual interface */ Property;\r
+struct __declspec(uuid("00000500-0000-0010-8000-00aa006d2ea4"))\r
+/* dual interface */ Error;\r
+struct __declspec(uuid("00000501-0000-0010-8000-00aa006d2ea4"))\r
+/* dual interface */ Errors;\r
+struct __declspec(uuid("00000508-0000-0010-8000-00aa006d2ea4"))\r
+/* dual interface */ Command15;\r
+struct __declspec(uuid("00000550-0000-0010-8000-00aa006d2ea4"))\r
+/* dual interface */ _Connection;\r
+struct __declspec(uuid("00000515-0000-0010-8000-00aa006d2ea4"))\r
+/* dual interface */ Connection15;\r
+struct __declspec(uuid("00000556-0000-0010-8000-00aa006d2ea4"))\r
+/* dual interface */ _Recordset;\r
+struct __declspec(uuid("00000555-0000-0010-8000-00aa006d2ea4"))\r
+/* dual interface */ Recordset21;\r
+struct __declspec(uuid("0000054f-0000-0010-8000-00aa006d2ea4"))\r
+/* dual interface */ Recordset20;\r
+struct __declspec(uuid("0000050e-0000-0010-8000-00aa006d2ea4"))\r
+/* dual interface */ Recordset15;\r
+struct __declspec(uuid("00000564-0000-0010-8000-00aa006d2ea4"))\r
+/* dual interface */ Fields;\r
+struct __declspec(uuid("0000054d-0000-0010-8000-00aa006d2ea4"))\r
+/* dual interface */ Fields20;\r
+struct __declspec(uuid("00000506-0000-0010-8000-00aa006d2ea4"))\r
+/* dual interface */ Fields15;\r
+struct __declspec(uuid("00000569-0000-0010-8000-00aa006d2ea4"))\r
+/* dual interface */ Field;\r
+struct __declspec(uuid("0000054c-0000-0010-8000-00aa006d2ea4"))\r
+/* dual interface */ Field20;\r
+struct __declspec(uuid("0000050c-0000-0010-8000-00aa006d2ea4"))\r
+/* dual interface */ _Parameter;\r
+struct __declspec(uuid("0000050d-0000-0010-8000-00aa006d2ea4"))\r
+/* dual interface */ Parameters;\r
+struct __declspec(uuid("0000054e-0000-0010-8000-00aa006d2ea4"))\r
+/* dual interface */ _Command;\r
+struct __declspec(uuid("00000402-0000-0010-8000-00aa006d2ea4"))\r
+/* interface */ ConnectionEventsVt;\r
+struct __declspec(uuid("00000403-0000-0010-8000-00aa006d2ea4"))\r
+/* interface */ RecordsetEventsVt;\r
+struct __declspec(uuid("00000400-0000-0010-8000-00aa006d2ea4"))\r
+/* dispinterface */ ConnectionEvents;\r
+struct __declspec(uuid("00000266-0000-0010-8000-00aa006d2ea4"))\r
+/* dispinterface */ RecordsetEvents;\r
+struct __declspec(uuid("00000516-0000-0010-8000-00aa006d2ea4"))\r
+/* interface */ ADOConnectionConstruction15;\r
+struct __declspec(uuid("00000551-0000-0010-8000-00aa006d2ea4"))\r
+/* interface */ ADOConnectionConstruction;\r
+struct /* coclass */ Connection;\r
+struct __declspec(uuid("00000562-0000-0010-8000-00aa006d2ea4"))\r
+/* dual interface */ _Record;\r
+struct /* coclass */ Record;\r
+struct __declspec(uuid("00000563-0000-0010-8000-00aa006d2ea4"))\r
+/* dual interface */ IRecFields;\r
+struct __declspec(uuid("00000565-0000-0010-8000-00aa006d2ea4"))\r
+/* dual interface */ _Stream;\r
+struct /* coclass */ Stream;\r
+struct __declspec(uuid("00000567-0000-0010-8000-00aa006d2ea4"))\r
+/* interface */ ADORecordConstruction;\r
+struct __declspec(uuid("00000568-0000-0010-8000-00aa006d2ea4"))\r
+/* interface */ ADOStreamConstruction;\r
+struct __declspec(uuid("00000517-0000-0010-8000-00aa006d2ea4"))\r
+/* interface */ ADOCommandConstruction;\r
+struct /* coclass */ Command;\r
+struct /* coclass */ Recordset;\r
+struct __declspec(uuid("00000283-0000-0010-8000-00aa006d2ea4"))\r
+/* interface */ ADORecordsetConstruction;\r
+struct __declspec(uuid("00000505-0000-0010-8000-00aa006d2ea4"))\r
+/* dual interface */ Field15;\r
+struct /* coclass */ Parameter;\r
+\r
+//\r
+// Smart pointer typedef declarations\r
+//\r
+\r
+_COM_SMARTPTR_TYPEDEF(_Collection, __uuidof(_Collection));\r
+_COM_SMARTPTR_TYPEDEF(_DynaCollection, __uuidof(_DynaCollection));\r
+_COM_SMARTPTR_TYPEDEF(_ADO, __uuidof(_ADO));\r
+_COM_SMARTPTR_TYPEDEF(Properties, __uuidof(Properties));\r
+_COM_SMARTPTR_TYPEDEF(Property, __uuidof(Property));\r
+_COM_SMARTPTR_TYPEDEF(Error, __uuidof(Error));\r
+_COM_SMARTPTR_TYPEDEF(Errors, __uuidof(Errors));\r
+_COM_SMARTPTR_TYPEDEF(Command15, __uuidof(Command15));\r
+_COM_SMARTPTR_TYPEDEF(Connection15, __uuidof(Connection15));\r
+_COM_SMARTPTR_TYPEDEF(_Connection, __uuidof(_Connection));\r
+_COM_SMARTPTR_TYPEDEF(Recordset15, __uuidof(Recordset15));\r
+_COM_SMARTPTR_TYPEDEF(Recordset20, __uuidof(Recordset20));\r
+_COM_SMARTPTR_TYPEDEF(Recordset21, __uuidof(Recordset21));\r
+_COM_SMARTPTR_TYPEDEF(_Recordset, __uuidof(_Recordset));\r
+_COM_SMARTPTR_TYPEDEF(Fields15, __uuidof(Fields15));\r
+_COM_SMARTPTR_TYPEDEF(Fields20, __uuidof(Fields20));\r
+_COM_SMARTPTR_TYPEDEF(Fields, __uuidof(Fields));\r
+_COM_SMARTPTR_TYPEDEF(Field20, __uuidof(Field20));\r
+_COM_SMARTPTR_TYPEDEF(Field, __uuidof(Field));\r
+_COM_SMARTPTR_TYPEDEF(_Parameter, __uuidof(_Parameter));\r
+_COM_SMARTPTR_TYPEDEF(Parameters, __uuidof(Parameters));\r
+_COM_SMARTPTR_TYPEDEF(_Command, __uuidof(_Command));\r
+_COM_SMARTPTR_TYPEDEF(ConnectionEventsVt, __uuidof(ConnectionEventsVt));\r
+_COM_SMARTPTR_TYPEDEF(RecordsetEventsVt, __uuidof(RecordsetEventsVt));\r
+_COM_SMARTPTR_TYPEDEF(ConnectionEvents, __uuidof(IDispatch));\r
+_COM_SMARTPTR_TYPEDEF(RecordsetEvents, __uuidof(IDispatch));\r
+_COM_SMARTPTR_TYPEDEF(ADOConnectionConstruction15, __uuidof(ADOConnectionConstruction15));\r
+_COM_SMARTPTR_TYPEDEF(ADOConnectionConstruction, __uuidof(ADOConnectionConstruction));\r
+_COM_SMARTPTR_TYPEDEF(_Record, __uuidof(_Record));\r
+_COM_SMARTPTR_TYPEDEF(IRecFields, __uuidof(IRecFields));\r
+_COM_SMARTPTR_TYPEDEF(_Stream, __uuidof(_Stream));\r
+_COM_SMARTPTR_TYPEDEF(ADORecordConstruction, __uuidof(ADORecordConstruction));\r
+_COM_SMARTPTR_TYPEDEF(ADOStreamConstruction, __uuidof(ADOStreamConstruction));\r
+_COM_SMARTPTR_TYPEDEF(ADOCommandConstruction, __uuidof(ADOCommandConstruction));\r
+_COM_SMARTPTR_TYPEDEF(ADORecordsetConstruction, __uuidof(ADORecordsetConstruction));\r
+_COM_SMARTPTR_TYPEDEF(Field15, __uuidof(Field15));\r
+\r
+//\r
+// Type library items\r
+//\r
+\r
+enum CursorTypeEnum\r
+{\r
+    adOpenUnspecified = -1,\r
+    adOpenForwardOnly = 0,\r
+    adOpenKeyset = 1,\r
+    adOpenDynamic = 2,\r
+    adOpenStatic = 3\r
+};\r
+\r
+enum CursorOptionEnum\r
+{\r
+    adHoldRecords = 256,\r
+    adMovePrevious = 512,\r
+    adAddNew = 16778240,\r
+    adDelete = 16779264,\r
+    adUpdate = 16809984,\r
+    adBookmark = 8192,\r
+    adApproxPosition = 16384,\r
+    adUpdateBatch = 65536,\r
+    adResync = 131072,\r
+    adNotify = 262144,\r
+    adFind = 524288,\r
+    adSeek = 4194304,\r
+    adIndex = 8388608\r
+};\r
+\r
+enum LockTypeEnum\r
+{\r
+    adLockUnspecified = -1,\r
+    adLockReadOnly = 1,\r
+    adLockPessimistic = 2,\r
+    adLockOptimistic = 3,\r
+    adLockBatchOptimistic = 4\r
+};\r
+\r
+enum ExecuteOptionEnum\r
+{\r
+    adOptionUnspecified = -1,\r
+    adAsyncExecute = 16,\r
+    adAsyncFetch = 32,\r
+    adAsyncFetchNonBlocking = 64,\r
+    adExecuteNoRecords = 128\r
+};\r
+\r
+enum ConnectOptionEnum\r
+{\r
+    adConnectUnspecified = -1,\r
+    adAsyncConnect = 16\r
+};\r
+\r
+enum ObjectStateEnum\r
+{\r
+    adStateClosed = 0,\r
+    adStateOpen = 1,\r
+    adStateConnecting = 2,\r
+    adStateExecuting = 4,\r
+    adStateFetching = 8\r
+};\r
+\r
+enum CursorLocationEnum\r
+{\r
+    adUseNone = 1,\r
+    adUseServer = 2,\r
+    adUseClient = 3,\r
+    adUseClientBatch = 3\r
+};\r
+\r
+enum DataTypeEnum\r
+{\r
+    adEmpty = 0,\r
+    adTinyInt = 16,\r
+    adSmallInt = 2,\r
+    adInteger = 3,\r
+    adBigInt = 20,\r
+    adUnsignedTinyInt = 17,\r
+    adUnsignedSmallInt = 18,\r
+    adUnsignedInt = 19,\r
+    adUnsignedBigInt = 21,\r
+    adSingle = 4,\r
+    adDouble = 5,\r
+    adCurrency = 6,\r
+    adDecimal = 14,\r
+    adNumeric = 131,\r
+    adBoolean = 11,\r
+    adError = 10,\r
+    adUserDefined = 132,\r
+    adVariant = 12,\r
+    adIDispatch = 9,\r
+    adIUnknown = 13,\r
+    adGUID = 72,\r
+    adDate = 7,\r
+    adDBDate = 133,\r
+    adDBTime = 134,\r
+    adDBTimeStamp = 135,\r
+    adBSTR = 8,\r
+    adChar = 129,\r
+    adVarChar = 200,\r
+    adLongVarChar = 201,\r
+    adWChar = 130,\r
+    adVarWChar = 202,\r
+    adLongVarWChar = 203,\r
+    adBinary = 128,\r
+    adVarBinary = 204,\r
+    adLongVarBinary = 205,\r
+    adChapter = 136,\r
+    adFileTime = 64,\r
+    adPropVariant = 138,\r
+    adVarNumeric = 139,\r
+    adArray = 8192\r
+};\r
+\r
+enum FieldAttributeEnum\r
+{\r
+    adFldUnspecified = -1,\r
+    adFldMayDefer = 2,\r
+    adFldUpdatable = 4,\r
+    adFldUnknownUpdatable = 8,\r
+    adFldFixed = 16,\r
+    adFldIsNullable = 32,\r
+    adFldMayBeNull = 64,\r
+    adFldLong = 128,\r
+    adFldRowID = 256,\r
+    adFldRowVersion = 512,\r
+    adFldCacheDeferred = 4096,\r
+    adFldIsChapter = 8192,\r
+    adFldNegativeScale = 16384,\r
+    adFldKeyColumn = 32768,\r
+    adFldIsRowURL = 65536,\r
+    adFldIsDefaultStream = 131072,\r
+    adFldIsCollection = 262144\r
+};\r
+\r
+enum EditModeEnum\r
+{\r
+    adEditNone = 0,\r
+    adEditInProgress = 1,\r
+    adEditAdd = 2,\r
+    adEditDelete = 4\r
+};\r
+\r
+enum RecordStatusEnum\r
+{\r
+    adRecOK = 0,\r
+    adRecNew = 1,\r
+    adRecModified = 2,\r
+    adRecDeleted = 4,\r
+    adRecUnmodified = 8,\r
+    adRecInvalid = 16,\r
+    adRecMultipleChanges = 64,\r
+    adRecPendingChanges = 128,\r
+    adRecCanceled = 256,\r
+    adRecCantRelease = 1024,\r
+    adRecConcurrencyViolation = 2048,\r
+    adRecIntegrityViolation = 4096,\r
+    adRecMaxChangesExceeded = 8192,\r
+    adRecObjectOpen = 16384,\r
+    adRecOutOfMemory = 32768,\r
+    adRecPermissionDenied = 65536,\r
+    adRecSchemaViolation = 131072,\r
+    adRecDBDeleted = 262144\r
+};\r
+\r
+enum GetRowsOptionEnum\r
+{\r
+    adGetRowsRest = -1\r
+};\r
+\r
+enum PositionEnum\r
+{\r
+    adPosUnknown = -1,\r
+    adPosBOF = -2,\r
+    adPosEOF = -3\r
+};\r
+\r
+enum BookmarkEnum\r
+{\r
+    adBookmarkCurrent = 0,\r
+    adBookmarkFirst = 1,\r
+    adBookmarkLast = 2\r
+};\r
+\r
+enum MarshalOptionsEnum\r
+{\r
+    adMarshalAll = 0,\r
+    adMarshalModifiedOnly = 1\r
+};\r
+\r
+enum AffectEnum\r
+{\r
+    adAffectCurrent = 1,\r
+    adAffectGroup = 2,\r
+    adAffectAll = 3,\r
+    adAffectAllChapters = 4\r
+};\r
+\r
+enum ResyncEnum\r
+{\r
+    adResyncUnderlyingValues = 1,\r
+    adResyncAllValues = 2\r
+};\r
+\r
+enum CompareEnum\r
+{\r
+    adCompareLessThan = 0,\r
+    adCompareEqual = 1,\r
+    adCompareGreaterThan = 2,\r
+    adCompareNotEqual = 3,\r
+    adCompareNotComparable = 4\r
+};\r
+\r
+enum FilterGroupEnum\r
+{\r
+    adFilterNone = 0,\r
+    adFilterPendingRecords = 1,\r
+    adFilterAffectedRecords = 2,\r
+    adFilterFetchedRecords = 3,\r
+    adFilterPredicate = 4,\r
+    adFilterConflictingRecords = 5\r
+};\r
+\r
+enum SearchDirectionEnum\r
+{\r
+    adSearchForward = 1,\r
+    adSearchBackward = -1\r
+};\r
+\r
+enum PersistFormatEnum\r
+{\r
+    adPersistADTG = 0,\r
+    adPersistXML = 1\r
+};\r
+\r
+enum StringFormatEnum\r
+{\r
+    adClipString = 2\r
+};\r
+\r
+enum ConnectPromptEnum\r
+{\r
+    adPromptAlways = 1,\r
+    adPromptComplete = 2,\r
+    adPromptCompleteRequired = 3,\r
+    adPromptNever = 4\r
+};\r
+\r
+enum ConnectModeEnum\r
+{\r
+    adModeUnknown = 0,\r
+    adModeRead = 1,\r
+    adModeWrite = 2,\r
+    adModeReadWrite = 3,\r
+    adModeShareDenyRead = 4,\r
+    adModeShareDenyWrite = 8,\r
+    adModeShareExclusive = 12,\r
+    adModeShareDenyNone = 16,\r
+    adModeRecursive = 4194304\r
+};\r
+\r
+enum RecordCreateOptionsEnum\r
+{\r
+    adCreateCollection = 8192,\r
+    adCreateStructDoc = -2147483648,\r
+    adCreateNonCollection = 0,\r
+    adOpenIfExists = 33554432,\r
+    adCreateOverwrite = 67108864,\r
+    adFailIfNotExists = -1\r
+};\r
+\r
+enum RecordOpenOptionsEnum\r
+{\r
+    adOpenRecordUnspecified = -1,\r
+    adOpenSource = 8388608,\r
+    adOpenAsync = 4096,\r
+    adDelayFetchStream = 16384,\r
+    adDelayFetchFields = 32768\r
+};\r
+\r
+enum IsolationLevelEnum\r
+{\r
+    adXactUnspecified = -1,\r
+    adXactChaos = 16,\r
+    adXactReadUncommitted = 256,\r
+    adXactBrowse = 256,\r
+    adXactCursorStability = 4096,\r
+    adXactReadCommitted = 4096,\r
+    adXactRepeatableRead = 65536,\r
+    adXactSerializable = 1048576,\r
+    adXactIsolated = 1048576\r
+};\r
+\r
+enum XactAttributeEnum\r
+{\r
+    adXactCommitRetaining = 131072,\r
+    adXactAbortRetaining = 262144,\r
+    adXactAsyncPhaseOne = 524288,\r
+    adXactSyncPhaseOne = 1048576\r
+};\r
+\r
+enum PropertyAttributesEnum\r
+{\r
+    adPropNotSupported = 0,\r
+    adPropRequired = 1,\r
+    adPropOptional = 2,\r
+    adPropRead = 512,\r
+    adPropWrite = 1024\r
+};\r
+\r
+enum ErrorValueEnum\r
+{\r
+    adErrProviderFailed = 3000,\r
+    adErrInvalidArgument = 3001,\r
+    adErrOpeningFile = 3002,\r
+    adErrReadFile = 3003,\r
+    adErrWriteFile = 3004,\r
+    adErrNoCurrentRecord = 3021,\r
+    adErrIllegalOperation = 3219,\r
+    adErrCantChangeProvider = 3220,\r
+    adErrInTransaction = 3246,\r
+    adErrFeatureNotAvailable = 3251,\r
+    adErrItemNotFound = 3265,\r
+    adErrObjectInCollection = 3367,\r
+    adErrObjectNotSet = 3420,\r
+    adErrDataConversion = 3421,\r
+    adErrObjectClosed = 3704,\r
+    adErrObjectOpen = 3705,\r
+    adErrProviderNotFound = 3706,\r
+    adErrBoundToCommand = 3707,\r
+    adErrInvalidParamInfo = 3708,\r
+    adErrInvalidConnection = 3709,\r
+    adErrNotReentrant = 3710,\r
+    adErrStillExecuting = 3711,\r
+    adErrOperationCancelled = 3712,\r
+    adErrStillConnecting = 3713,\r
+    adErrInvalidTransaction = 3714,\r
+    adErrNotExecuting = 3715,\r
+    adErrUnsafeOperation = 3716,\r
+    adwrnSecurityDialog = 3717,\r
+    adwrnSecurityDialogHeader = 3718,\r
+    adErrIntegrityViolation = 3719,\r
+    adErrPermissionDenied = 3720,\r
+    adErrDataOverflow = 3721,\r
+    adErrSchemaViolation = 3722,\r
+    adErrSignMismatch = 3723,\r
+    adErrCantConvertvalue = 3724,\r
+    adErrCantCreate = 3725,\r
+    adErrColumnNotOnThisRow = 3726,\r
+    adErrURLDoesNotExist = 3727,\r
+    adErrTreePermissionDenied = 3728,\r
+    adErrInvalidURL = 3729,\r
+    adErrResourceLocked = 3730,\r
+    adErrResourceExists = 3731,\r
+    adErrCannotComplete = 3732,\r
+    adErrVolumeNotFound = 3733,\r
+    adErrOutOfSpace = 3734,\r
+    adErrResourceOutOfScope = 3735,\r
+    adErrUnavailable = 3736,\r
+    adErrURLNamedRowDoesNotExist = 3737,\r
+    adErrDelResOutOfScope = 3738,\r
+    adErrPropInvalidColumn = 3739,\r
+    adErrPropInvalidOption = 3740,\r
+    adErrPropInvalidValue = 3741,\r
+    adErrPropConflicting = 3742,\r
+    adErrPropNotAllSettable = 3743,\r
+    adErrPropNotSet = 3744,\r
+    adErrPropNotSettable = 3745,\r
+    adErrPropNotSupported = 3746,\r
+    adErrCatalogNotSet = 3747,\r
+    adErrCantChangeConnection = 3748,\r
+    adErrFieldsUpdateFailed = 3749,\r
+    adErrDenyNotSupported = 3750,\r
+    adErrDenyTypeNotSupported = 3751\r
+};\r
+\r
+enum ParameterAttributesEnum\r
+{\r
+    adParamSigned = 16,\r
+    adParamNullable = 64,\r
+    adParamLong = 128\r
+};\r
+\r
+enum ParameterDirectionEnum\r
+{\r
+    adParamUnknown = 0,\r
+    adParamInput = 1,\r
+    adParamOutput = 2,\r
+    adParamInputOutput = 3,\r
+    adParamReturnValue = 4\r
+};\r
+\r
+enum CommandTypeEnum\r
+{\r
+    adCmdUnspecified = -1,\r
+    adCmdUnknown = 8,\r
+    adCmdText = 1,\r
+    adCmdTable = 2,\r
+    adCmdStoredProc = 4,\r
+    adCmdFile = 256,\r
+    adCmdTableDirect = 512\r
+};\r
+\r
+enum EventStatusEnum\r
+{\r
+    adStatusOK = 1,\r
+    adStatusErrorsOccurred = 2,\r
+    adStatusCantDeny = 3,\r
+    adStatusCancel = 4,\r
+    adStatusUnwantedEvent = 5\r
+};\r
+\r
+enum EventReasonEnum\r
+{\r
+    adRsnAddNew = 1,\r
+    adRsnDelete = 2,\r
+    adRsnUpdate = 3,\r
+    adRsnUndoUpdate = 4,\r
+    adRsnUndoAddNew = 5,\r
+    adRsnUndoDelete = 6,\r
+    adRsnRequery = 7,\r
+    adRsnResynch = 8,\r
+    adRsnClose = 9,\r
+    adRsnMove = 10,\r
+    adRsnFirstChange = 11,\r
+    adRsnMoveFirst = 12,\r
+    adRsnMoveNext = 13,\r
+    adRsnMovePrevious = 14,\r
+    adRsnMoveLast = 15\r
+};\r
+\r
+enum SchemaEnum\r
+{\r
+    adSchemaProviderSpecific = -1,\r
+    adSchemaAsserts = 0,\r
+    adSchemaCatalogs = 1,\r
+    adSchemaCharacterSets = 2,\r
+    adSchemaCollations = 3,\r
+    adSchemaColumns = 4,\r
+    adSchemaCheckConstraints = 5,\r
+    adSchemaConstraintColumnUsage = 6,\r
+    adSchemaConstraintTableUsage = 7,\r
+    adSchemaKeyColumnUsage = 8,\r
+    adSchemaReferentialContraints = 9,\r
+    adSchemaReferentialConstraints = 9,\r
+    adSchemaTableConstraints = 10,\r
+    adSchemaColumnsDomainUsage = 11,\r
+    adSchemaIndexes = 12,\r
+    adSchemaColumnPrivileges = 13,\r
+    adSchemaTablePrivileges = 14,\r
+    adSchemaUsagePrivileges = 15,\r
+    adSchemaProcedures = 16,\r
+    adSchemaSchemata = 17,\r
+    adSchemaSQLLanguages = 18,\r
+    adSchemaStatistics = 19,\r
+    adSchemaTables = 20,\r
+    adSchemaTranslations = 21,\r
+    adSchemaProviderTypes = 22,\r
+    adSchemaViews = 23,\r
+    adSchemaViewColumnUsage = 24,\r
+    adSchemaViewTableUsage = 25,\r
+    adSchemaProcedureParameters = 26,\r
+    adSchemaForeignKeys = 27,\r
+    adSchemaPrimaryKeys = 28,\r
+    adSchemaProcedureColumns = 29,\r
+    adSchemaDBInfoKeywords = 30,\r
+    adSchemaDBInfoLiterals = 31,\r
+    adSchemaCubes = 32,\r
+    adSchemaDimensions = 33,\r
+    adSchemaHierarchies = 34,\r
+    adSchemaLevels = 35,\r
+    adSchemaMeasures = 36,\r
+    adSchemaProperties = 37,\r
+    adSchemaMembers = 38,\r
+    adSchemaTrustees = 39\r
+};\r
+\r
+enum FieldStatusEnum\r
+{\r
+    adFieldOK = 0,\r
+    adFieldCantConvertValue = 2,\r
+    adFieldIsNull = 3,\r
+    adFieldTruncated = 4,\r
+    adFieldSignMismatch = 5,\r
+    adFieldDataOverflow = 6,\r
+    adFieldCantCreate = 7,\r
+    adFieldUnavailable = 8,\r
+    adFieldPermissionDenied = 9,\r
+    adFieldIntegrityViolation = 10,\r
+    adFieldSchemaViolation = 11,\r
+    adFieldBadStatus = 12,\r
+    adFieldDefault = 13,\r
+    adFieldIgnore = 15,\r
+    adFieldDoesNotExist = 16,\r
+    adFieldInvalidURL = 17,\r
+    adFieldResourceLocked = 18,\r
+    adFieldResourceExists = 19,\r
+    adFieldCannotComplete = 20,\r
+    adFieldVolumeNotFound = 21,\r
+    adFieldOutOfSpace = 22,\r
+    adFieldCannotDeleteSource = 23,\r
+    adFieldReadOnly = 24,\r
+    adFieldResourceOutOfScope = 25,\r
+    adFieldAlreadyExists = 26,\r
+    adFieldPendingInsert = 65536,\r
+    adFieldPendingDelete = 131072,\r
+    adFieldPendingChange = 262144,\r
+    adFieldPendingUnknown = 524288,\r
+    adFieldPendingUnknownDelete = 1048576\r
+};\r
+\r
+enum SeekEnum\r
+{\r
+    adSeekFirstEQ = 1,\r
+    adSeekLastEQ = 2,\r
+    adSeekAfterEQ = 4,\r
+    adSeekAfter = 8,\r
+    adSeekBeforeEQ = 16,\r
+    adSeekBefore = 32\r
+};\r
+\r
+enum ADCPROP_UPDATECRITERIA_ENUM\r
+{\r
+    adCriteriaKey = 0,\r
+    adCriteriaAllCols = 1,\r
+    adCriteriaUpdCols = 2,\r
+    adCriteriaTimeStamp = 3\r
+};\r
+\r
+enum ADCPROP_ASYNCTHREADPRIORITY_ENUM\r
+{\r
+    adPriorityLowest = 1,\r
+    adPriorityBelowNormal = 2,\r
+    adPriorityNormal = 3,\r
+    adPriorityAboveNormal = 4,\r
+    adPriorityHighest = 5\r
+};\r
+\r
+enum ADCPROP_AUTORECALC_ENUM\r
+{\r
+    adRecalcUpFront = 0,\r
+    adRecalcAlways = 1\r
+};\r
+\r
+enum ADCPROP_UPDATERESYNC_ENUM\r
+{\r
+    adResyncNone = 0,\r
+    adResyncAutoIncrement = 1,\r
+    adResyncConflicts = 2,\r
+    adResyncUpdates = 4,\r
+    adResyncInserts = 8,\r
+    adResyncAll = 15\r
+};\r
+\r
+enum MoveRecordOptionsEnum\r
+{\r
+    adMoveUnspecified = -1,\r
+    adMoveOverWrite = 1,\r
+    adMoveDontUpdateLinks = 2,\r
+    adMoveAllowEmulation = 4\r
+};\r
+\r
+enum CopyRecordOptionsEnum\r
+{\r
+    adCopyUnspecified = -1,\r
+    adCopyOverWrite = 1,\r
+    adCopyAllowEmulation = 4,\r
+    adCopyNonRecursive = 2\r
+};\r
+\r
+enum StreamTypeEnum\r
+{\r
+    adTypeBinary = 1,\r
+    adTypeText = 2\r
+};\r
+\r
+enum LineSeparatorEnum\r
+{\r
+    adLF = 10,\r
+    adCR = 13,\r
+    adCRLF = -1\r
+};\r
+\r
+enum StreamOpenOptionsEnum\r
+{\r
+    adOpenStreamUnspecified = -1,\r
+    adOpenStreamAsync = 1,\r
+    adOpenStreamFromRecord = 4\r
+};\r
+\r
+enum StreamWriteEnum\r
+{\r
+    adWriteChar = 0,\r
+    adWriteLine = 1,\r
+    stWriteChar = 0,\r
+    stWriteLine = 1\r
+};\r
+\r
+enum SaveOptionsEnum\r
+{\r
+    adSaveCreateNotExist = 1,\r
+    adSaveCreateOverWrite = 2\r
+};\r
+\r
+enum FieldEnum\r
+{\r
+    adDefaultStream = -1,\r
+    adRecordURL = -2\r
+};\r
+\r
+enum StreamReadEnum\r
+{\r
+    adReadAll = -1,\r
+    adReadLine = -2\r
+};\r
+\r
+enum RecordTypeEnum\r
+{\r
+    adSimpleRecord = 0,\r
+    adCollectionRecord = 1,\r
+    adStructDoc = 2\r
+};\r
+\r
+struct __declspec(uuid("00000512-0000-0010-8000-00aa006d2ea4"))\r
+_Collection : IDispatch\r
+{\r
+    //\r
+    // Property data\r
+    //\r
+\r
+    __declspec(property(get=GetCount))\r
+    long Count;\r
+\r
+    //\r
+    // Wrapper methods for error-handling\r
+    //\r
+\r
+    long GetCount ( );\r
+    IUnknownPtr _NewEnum ( );\r
+    HRESULT Refresh ( );\r
+\r
+    //\r
+    // Raw methods provided by interface\r
+    //\r
+\r
+    virtual HRESULT __stdcall get_Count (\r
+        long * c ) = 0;\r
+    virtual HRESULT __stdcall raw__NewEnum (\r
+        IUnknown * * ppvObject ) = 0;\r
+    virtual HRESULT __stdcall raw_Refresh ( ) = 0;\r
+};\r
+\r
+struct __declspec(uuid("00000513-0000-0010-8000-00aa006d2ea4"))\r
+_DynaCollection : _Collection\r
+{\r
+    //\r
+    // Wrapper methods for error-handling\r
+    //\r
+\r
+    HRESULT Append (\r
+        IDispatch * Object );\r
+    HRESULT Delete (\r
+        const _variant_t & Index );\r
+\r
+    //\r
+    // Raw methods provided by interface\r
+    //\r
+\r
+    virtual HRESULT __stdcall raw_Append (\r
+        IDispatch * Object ) = 0;\r
+    virtual HRESULT __stdcall raw_Delete (\r
+        VARIANT Index ) = 0;\r
+};\r
+\r
+struct __declspec(uuid("00000534-0000-0010-8000-00aa006d2ea4"))\r
+_ADO : IDispatch\r
+{\r
+    //\r
+    // Property data\r
+    //\r
+\r
+    __declspec(property(get=GetProperties))\r
+    PropertiesPtr Properties;\r
+\r
+    //\r
+    // Wrapper methods for error-handling\r
+    //\r
+\r
+    PropertiesPtr GetProperties ( );\r
+\r
+    //\r
+    // Raw methods provided by interface\r
+    //\r
+\r
+    virtual HRESULT __stdcall get_Properties (\r
+        struct Properties * * ppvObject ) = 0;\r
+};\r
+\r
+struct __declspec(uuid("00000504-0000-0010-8000-00aa006d2ea4"))\r
+Properties : _Collection\r
+{\r
+    //\r
+    // Property data\r
+    //\r
+\r
+    __declspec(property(get=GetItem))\r
+    PropertyPtr Item[];\r
+\r
+    //\r
+    // Wrapper methods for error-handling\r
+    //\r
+\r
+    PropertyPtr GetItem (\r
+        const _variant_t & Index );\r
+\r
+    //\r
+    // Raw methods provided by interface\r
+    //\r
+\r
+    virtual HRESULT __stdcall get_Item (\r
+        VARIANT Index,\r
+        struct Property * * ppvObject ) = 0;\r
+};\r
+\r
+struct __declspec(uuid("00000503-0000-0010-8000-00aa006d2ea4"))\r
+Property : IDispatch\r
+{\r
+    //\r
+    // Property data\r
+    //\r
+\r
+    __declspec(property(get=GetValue,put=PutValue))\r
+    _variant_t Value;\r
+    __declspec(property(get=GetName))\r
+    _bstr_t Name;\r
+    __declspec(property(get=GetType))\r
+    enum DataTypeEnum Type;\r
+    __declspec(property(get=GetAttributes,put=PutAttributes))\r
+    long Attributes;\r
+\r
+    //\r
+    // Wrapper methods for error-handling\r
+    //\r
+\r
+    _variant_t GetValue ( );\r
+    void PutValue (\r
+        const _variant_t & pval );\r
+    _bstr_t GetName ( );\r
+    enum DataTypeEnum GetType ( );\r
+    long GetAttributes ( );\r
+    void PutAttributes (\r
+        long plAttributes );\r
+\r
+    //\r
+    // Raw methods provided by interface\r
+    //\r
+\r
+    virtual HRESULT __stdcall get_Value (\r
+        VARIANT * pval ) = 0;\r
+    virtual HRESULT __stdcall put_Value (\r
+        VARIANT pval ) = 0;\r
+    virtual HRESULT __stdcall get_Name (\r
+        BSTR * pbstr ) = 0;\r
+    virtual HRESULT __stdcall get_Type (\r
+        enum DataTypeEnum * ptype ) = 0;\r
+    virtual HRESULT __stdcall get_Attributes (\r
+        long * plAttributes ) = 0;\r
+    virtual HRESULT __stdcall put_Attributes (\r
+        long plAttributes ) = 0;\r
+};\r
+\r
+struct __declspec(uuid("00000500-0000-0010-8000-00aa006d2ea4"))\r
+Error : IDispatch\r
+{\r
+    //\r
+    // Property data\r
+    //\r
+\r
+    __declspec(property(get=GetDescription))\r
+    _bstr_t Description;\r
+    __declspec(property(get=GetNumber))\r
+    long Number;\r
+    __declspec(property(get=GetSource))\r
+    _bstr_t Source;\r
+    __declspec(property(get=GetHelpFile))\r
+    _bstr_t HelpFile;\r
+    __declspec(property(get=GetHelpContext))\r
+    long HelpContext;\r
+    __declspec(property(get=GetSQLState))\r
+    _bstr_t SQLState;\r
+    __declspec(property(get=GetNativeError))\r
+    long NativeError;\r
+\r
+    //\r
+    // Wrapper methods for error-handling\r
+    //\r
+\r
+    long GetNumber ( );\r
+    _bstr_t GetSource ( );\r
+    _bstr_t GetDescription ( );\r
+    _bstr_t GetHelpFile ( );\r
+    long GetHelpContext ( );\r
+    _bstr_t GetSQLState ( );\r
+    long GetNativeError ( );\r
+\r
+    //\r
+    // Raw methods provided by interface\r
+    //\r
+\r
+    virtual HRESULT __stdcall get_Number (\r
+        long * pl ) = 0;\r
+    virtual HRESULT __stdcall get_Source (\r
+        BSTR * pbstr ) = 0;\r
+    virtual HRESULT __stdcall get_Description (\r
+        BSTR * pbstr ) = 0;\r
+    virtual HRESULT __stdcall get_HelpFile (\r
+        BSTR * pbstr ) = 0;\r
+    virtual HRESULT __stdcall get_HelpContext (\r
+        long * pl ) = 0;\r
+    virtual HRESULT __stdcall get_SQLState (\r
+        BSTR * pbstr ) = 0;\r
+    virtual HRESULT __stdcall get_NativeError (\r
+        long * pl ) = 0;\r
+};\r
+\r
+struct __declspec(uuid("00000501-0000-0010-8000-00aa006d2ea4"))\r
+Errors : _Collection\r
+{\r
+    //\r
+    // Property data\r
+    //\r
+\r
+    __declspec(property(get=GetItem))\r
+    ErrorPtr Item[];\r
+\r
+    //\r
+    // Wrapper methods for error-handling\r
+    //\r
+\r
+    ErrorPtr GetItem (\r
+        const _variant_t & Index );\r
+    HRESULT Clear ( );\r
+\r
+    //\r
+    // Raw methods provided by interface\r
+    //\r
+\r
+    virtual HRESULT __stdcall get_Item (\r
+        VARIANT Index,\r
+        struct Error * * ppvObject ) = 0;\r
+    virtual HRESULT __stdcall raw_Clear ( ) = 0;\r
+};\r
+\r
+struct __declspec(uuid("00000508-0000-0010-8000-00aa006d2ea4"))\r
+Command15 : _ADO\r
+{\r
+    //\r
+    // Property data\r
+    //\r
+\r
+    __declspec(property(get=GetParameters))\r
+    ParametersPtr Parameters;\r
+    __declspec(property(get=GetActiveConnection,put=PutRefActiveConnection))\r
+    _ConnectionPtr ActiveConnection;\r
+    __declspec(property(get=GetCommandText,put=PutCommandText))\r
+    _bstr_t CommandText;\r
+    __declspec(property(get=GetCommandTimeout,put=PutCommandTimeout))\r
+    long CommandTimeout;\r
+    __declspec(property(get=GetPrepared,put=PutPrepared))\r
+    VARIANT_BOOL Prepared;\r
+    __declspec(property(get=GetCommandType,put=PutCommandType))\r
+    enum CommandTypeEnum CommandType;\r
+    __declspec(property(get=GetName,put=PutName))\r
+    _bstr_t Name;\r
+\r
+    //\r
+    // Wrapper methods for error-handling\r
+    //\r
+\r
+    _ConnectionPtr GetActiveConnection ( );\r
+    void PutRefActiveConnection (\r
+        struct _Connection * ppvObject );\r
+    void PutActiveConnection (\r
+        const _variant_t & ppvObject );\r
+    _bstr_t GetCommandText ( );\r
+    void PutCommandText (\r
+        _bstr_t pbstr );\r
+    long GetCommandTimeout ( );\r
+    void PutCommandTimeout (\r
+        long pl );\r
+    VARIANT_BOOL GetPrepared ( );\r
+    void PutPrepared (\r
+        VARIANT_BOOL pfPrepared );\r
+    _RecordsetPtr Execute (\r
+        VARIANT * RecordsAffected,\r
+        VARIANT * Parameters,\r
+        long Options );\r
+    _ParameterPtr CreateParameter (\r
+        _bstr_t Name,\r
+        enum DataTypeEnum Type,\r
+        enum ParameterDirectionEnum Direction,\r
+        long Size,\r
+        const _variant_t & Value = vtMissing );\r
+    ParametersPtr GetParameters ( );\r
+    void PutCommandType (\r
+        enum CommandTypeEnum plCmdType );\r
+    enum CommandTypeEnum GetCommandType ( );\r
+    _bstr_t GetName ( );\r
+    void PutName (\r
+        _bstr_t pbstrName );\r
+\r
+    //\r
+    // Raw methods provided by interface\r
+    //\r
+\r
+    virtual HRESULT __stdcall get_ActiveConnection (\r
+        struct _Connection * * ppvObject ) = 0;\r
+    virtual HRESULT __stdcall putref_ActiveConnection (\r
+        struct _Connection * ppvObject ) = 0;\r
+    virtual HRESULT __stdcall put_ActiveConnection (\r
+        VARIANT ppvObject ) = 0;\r
+    virtual HRESULT __stdcall get_CommandText (\r
+        BSTR * pbstr ) = 0;\r
+    virtual HRESULT __stdcall put_CommandText (\r
+        BSTR pbstr ) = 0;\r
+    virtual HRESULT __stdcall get_CommandTimeout (\r
+        long * pl ) = 0;\r
+    virtual HRESULT __stdcall put_CommandTimeout (\r
+        long pl ) = 0;\r
+    virtual HRESULT __stdcall get_Prepared (\r
+        VARIANT_BOOL * pfPrepared ) = 0;\r
+    virtual HRESULT __stdcall put_Prepared (\r
+        VARIANT_BOOL pfPrepared ) = 0;\r
+    virtual HRESULT __stdcall raw_Execute (\r
+        VARIANT * RecordsAffected,\r
+        VARIANT * Parameters,\r
+        long Options,\r
+        struct _Recordset * * ppiRs ) = 0;\r
+    virtual HRESULT __stdcall raw_CreateParameter (\r
+        BSTR Name,\r
+        enum DataTypeEnum Type,\r
+        enum ParameterDirectionEnum Direction,\r
+        long Size,\r
+        VARIANT Value,\r
+        struct _Parameter * * ppiprm ) = 0;\r
+    virtual HRESULT __stdcall get_Parameters (\r
+        struct Parameters * * ppvObject ) = 0;\r
+    virtual HRESULT __stdcall put_CommandType (\r
+        enum CommandTypeEnum plCmdType ) = 0;\r
+    virtual HRESULT __stdcall get_CommandType (\r
+        enum CommandTypeEnum * plCmdType ) = 0;\r
+    virtual HRESULT __stdcall get_Name (\r
+        BSTR * pbstrName ) = 0;\r
+    virtual HRESULT __stdcall put_Name (\r
+        BSTR pbstrName ) = 0;\r
+};\r
+\r
+struct __declspec(uuid("00000515-0000-0010-8000-00aa006d2ea4"))\r
+Connection15 : _ADO\r
+{\r
+    //\r
+    // Property data\r
+    //\r
+\r
+    __declspec(property(get=GetConnectionString,put=PutConnectionString))\r
+    _bstr_t ConnectionString;\r
+    __declspec(property(get=GetCommandTimeout,put=PutCommandTimeout))\r
+    long CommandTimeout;\r
+    __declspec(property(get=GetConnectionTimeout,put=PutConnectionTimeout))\r
+    long ConnectionTimeout;\r
+    __declspec(property(get=GetVersion))\r
+    _bstr_t Version;\r
+    __declspec(property(get=GetErrors))\r
+    ErrorsPtr Errors;\r
+    __declspec(property(get=GetDefaultDatabase,put=PutDefaultDatabase))\r
+    _bstr_t DefaultDatabase;\r
+    __declspec(property(get=GetIsolationLevel,put=PutIsolationLevel))\r
+    enum IsolationLevelEnum IsolationLevel;\r
+    __declspec(property(get=GetAttributes,put=PutAttributes))\r
+    long Attributes;\r
+    __declspec(property(get=GetCursorLocation,put=PutCursorLocation))\r
+    enum CursorLocationEnum CursorLocation;\r
+    __declspec(property(get=GetMode,put=PutMode))\r
+    enum ConnectModeEnum Mode;\r
+    __declspec(property(get=GetProvider,put=PutProvider))\r
+    _bstr_t Provider;\r
+    __declspec(property(get=GetState))\r
+    long State;\r
+\r
+    //\r
+    // Wrapper methods for error-handling\r
+    //\r
+\r
+    _bstr_t GetConnectionString ( );\r
+    void PutConnectionString (\r
+        _bstr_t pbstr );\r
+    long GetCommandTimeout ( );\r
+    void PutCommandTimeout (\r
+        long plTimeout );\r
+    long GetConnectionTimeout ( );\r
+    void PutConnectionTimeout (\r
+        long plTimeout );\r
+    _bstr_t GetVersion ( );\r
+    HRESULT Close ( );\r
+    _RecordsetPtr Execute (\r
+        _bstr_t CommandText,\r
+        VARIANT * RecordsAffected,\r
+        long Options );\r
+    long BeginTrans ( );\r
+    HRESULT CommitTrans ( );\r
+    HRESULT RollbackTrans ( );\r
+    HRESULT Open (\r
+        _bstr_t ConnectionString,\r
+        _bstr_t UserID,\r
+        _bstr_t Password,\r
+        long Options );\r
+    ErrorsPtr GetErrors ( );\r
+    _bstr_t GetDefaultDatabase ( );\r
+    void PutDefaultDatabase (\r
+        _bstr_t pbstr );\r
+    enum IsolationLevelEnum GetIsolationLevel ( );\r
+    void PutIsolationLevel (\r
+        enum IsolationLevelEnum Level );\r
+    long GetAttributes ( );\r
+    void PutAttributes (\r
+        long plAttr );\r
+    enum CursorLocationEnum GetCursorLocation ( );\r
+    void PutCursorLocation (\r
+        enum CursorLocationEnum plCursorLoc );\r
+    enum ConnectModeEnum GetMode ( );\r
+    void PutMode (\r
+        enum ConnectModeEnum plMode );\r
+    _bstr_t GetProvider ( );\r
+    void PutProvider (\r
+        _bstr_t pbstr );\r
+    long GetState ( );\r
+    _RecordsetPtr OpenSchema (\r
+        enum SchemaEnum Schema,\r
+        const _variant_t & Restrictions = vtMissing,\r
+        const _variant_t & SchemaID = vtMissing );\r
+\r
+    //\r
+    // Raw methods provided by interface\r
+    //\r
+\r
+    virtual HRESULT __stdcall get_ConnectionString (\r
+        BSTR * pbstr ) = 0;\r
+    virtual HRESULT __stdcall put_ConnectionString (\r
+        BSTR pbstr ) = 0;\r
+    virtual HRESULT __stdcall get_CommandTimeout (\r
+        long * plTimeout ) = 0;\r
+    virtual HRESULT __stdcall put_CommandTimeout (\r
+        long plTimeout ) = 0;\r
+    virtual HRESULT __stdcall get_ConnectionTimeout (\r
+        long * plTimeout ) = 0;\r
+    virtual HRESULT __stdcall put_ConnectionTimeout (\r
+        long plTimeout ) = 0;\r
+    virtual HRESULT __stdcall get_Version (\r
+        BSTR * pbstr ) = 0;\r
+    virtual HRESULT __stdcall raw_Close ( ) = 0;\r
+    virtual HRESULT __stdcall raw_Execute (\r
+        BSTR CommandText,\r
+        VARIANT * RecordsAffected,\r
+        long Options,\r
+        struct _Recordset * * ppiRset ) = 0;\r
+    virtual HRESULT __stdcall raw_BeginTrans (\r
+        long * TransactionLevel ) = 0;\r
+    virtual HRESULT __stdcall raw_CommitTrans ( ) = 0;\r
+    virtual HRESULT __stdcall raw_RollbackTrans ( ) = 0;\r
+    virtual HRESULT __stdcall raw_Open (\r
+        BSTR ConnectionString,\r
+        BSTR UserID,\r
+        BSTR Password,\r
+        long Options ) = 0;\r
+    virtual HRESULT __stdcall get_Errors (\r
+        struct Errors * * ppvObject ) = 0;\r
+    virtual HRESULT __stdcall get_DefaultDatabase (\r
+        BSTR * pbstr ) = 0;\r
+    virtual HRESULT __stdcall put_DefaultDatabase (\r
+        BSTR pbstr ) = 0;\r
+    virtual HRESULT __stdcall get_IsolationLevel (\r
+        enum IsolationLevelEnum * Level ) = 0;\r
+    virtual HRESULT __stdcall put_IsolationLevel (\r
+        enum IsolationLevelEnum Level ) = 0;\r
+    virtual HRESULT __stdcall get_Attributes (\r
+        long * plAttr ) = 0;\r
+    virtual HRESULT __stdcall put_Attributes (\r
+        long plAttr ) = 0;\r
+    virtual HRESULT __stdcall get_CursorLocation (\r
+        enum CursorLocationEnum * plCursorLoc ) = 0;\r
+    virtual HRESULT __stdcall put_CursorLocation (\r
+        enum CursorLocationEnum plCursorLoc ) = 0;\r
+    virtual HRESULT __stdcall get_Mode (\r
+        enum ConnectModeEnum * plMode ) = 0;\r
+    virtual HRESULT __stdcall put_Mode (\r
+        enum ConnectModeEnum plMode ) = 0;\r
+    virtual HRESULT __stdcall get_Provider (\r
+        BSTR * pbstr ) = 0;\r
+    virtual HRESULT __stdcall put_Provider (\r
+        BSTR pbstr ) = 0;\r
+    virtual HRESULT __stdcall get_State (\r
+        long * plObjState ) = 0;\r
+    virtual HRESULT __stdcall raw_OpenSchema (\r
+        enum SchemaEnum Schema,\r
+        VARIANT Restrictions,\r
+        VARIANT SchemaID,\r
+        struct _Recordset * * pprset ) = 0;\r
+};\r
+\r
+struct __declspec(uuid("00000550-0000-0010-8000-00aa006d2ea4"))\r
+_Connection : Connection15\r
+{\r
+    //\r
+    // Wrapper methods for error-handling\r
+    //\r
+\r
+    HRESULT Cancel ( );\r
+\r
+    //\r
+    // Raw methods provided by interface\r
+    //\r
+\r
+    virtual HRESULT __stdcall raw_Cancel ( ) = 0;\r
+};\r
+\r
+struct __declspec(uuid("0000050e-0000-0010-8000-00aa006d2ea4"))\r
+Recordset15 : _ADO\r
+{\r
+    //\r
+    // Property data\r
+    //\r
+\r
+    __declspec(property(get=GetFields))\r
+    FieldsPtr Fields;\r
+    __declspec(property(get=GetPageSize,put=PutPageSize))\r
+    long PageSize;\r
+    __declspec(property(get=GetPageCount))\r
+    long PageCount;\r
+    __declspec(property(get=GetCursorLocation,put=PutCursorLocation))\r
+    enum CursorLocationEnum CursorLocation;\r
+    __declspec(property(get=GetState))\r
+    long State;\r
+    __declspec(property(get=GetMarshalOptions,put=PutMarshalOptions))\r
+    enum MarshalOptionsEnum MarshalOptions;\r
+    __declspec(property(get=GetCollect,put=PutCollect))\r
+    _variant_t Collect[];\r
+    __declspec(property(get=GetEditMode))\r
+    enum EditModeEnum EditMode;\r
+    __declspec(property(get=GetStatus))\r
+    long Status;\r
+    __declspec(property(get=GetFilter,put=PutFilter))\r
+    _variant_t Filter;\r
+    __declspec(property(get=GetSort,put=PutSort))\r
+    _bstr_t Sort;\r
+    __declspec(property(get=GetAbsolutePosition,put=PutAbsolutePosition))\r
+    enum PositionEnum AbsolutePosition;\r
+    __declspec(property(get=GetBOF))\r
+    VARIANT_BOOL BOF;\r
+    __declspec(property(get=GetBookmark,put=PutBookmark))\r
+    _variant_t Bookmark;\r
+    __declspec(property(get=GetCacheSize,put=PutCacheSize))\r
+    long CacheSize;\r
+    __declspec(property(get=GetCursorType,put=PutCursorType))\r
+    enum CursorTypeEnum CursorType;\r
+    __declspec(property(get=GetadoEOF))\r
+    VARIANT_BOOL adoEOF;\r
+    __declspec(property(get=GetAbsolutePage,put=PutAbsolutePage))\r
+    enum PositionEnum AbsolutePage;\r
+    __declspec(property(get=GetLockType,put=PutLockType))\r
+    enum LockTypeEnum LockType;\r
+    __declspec(property(get=GetMaxRecords,put=PutMaxRecords))\r
+    long MaxRecords;\r
+    __declspec(property(get=GetRecordCount))\r
+    long RecordCount;\r
+\r
+    //\r
+    // Wrapper methods for error-handling\r
+    //\r
+\r
+    enum PositionEnum GetAbsolutePosition ( );\r
+    void PutAbsolutePosition (\r
+        enum PositionEnum pl );\r
+    void PutRefActiveConnection (\r
+        IDispatch * pvar );\r
+    void PutActiveConnection (\r
+        const _variant_t & pvar );\r
+    _variant_t GetActiveConnection ( );\r
+    VARIANT_BOOL GetBOF ( );\r
+    _variant_t GetBookmark ( );\r
+    void PutBookmark (\r
+        const _variant_t & pvBookmark );\r
+    long GetCacheSize ( );\r
+    void PutCacheSize (\r
+        long pl );\r
+    enum CursorTypeEnum GetCursorType ( );\r
+    void PutCursorType (\r
+        enum CursorTypeEnum plCursorType );\r
+    VARIANT_BOOL GetadoEOF ( );\r
+    FieldsPtr GetFields ( );\r
+    enum LockTypeEnum GetLockType ( );\r
+    void PutLockType (\r
+        enum LockTypeEnum plLockType );\r
+    long GetMaxRecords ( );\r
+    void PutMaxRecords (\r
+        long plMaxRecords );\r
+    long GetRecordCount ( );\r
+    void PutRefSource (\r
+        IDispatch * pvSource );\r
+    void PutSource (\r
+        _bstr_t pvSource );\r
+    _variant_t GetSource ( );\r
+    HRESULT AddNew (\r
+        const _variant_t & FieldList = vtMissing,\r
+        const _variant_t & Values = vtMissing );\r
+    HRESULT CancelUpdate ( );\r
+    HRESULT Close ( );\r
+    HRESULT Delete (\r
+        enum AffectEnum AffectRecords );\r
+    _variant_t GetRows (\r
+        long Rows,\r
+        const _variant_t & Start = vtMissing,\r
+        const _variant_t & Fields = vtMissing );\r
+    HRESULT Move (\r
+        long NumRecords,\r
+        const _variant_t & Start = vtMissing );\r
+    HRESULT MoveNext ( );\r
+    HRESULT MovePrevious ( );\r
+    HRESULT MoveFirst ( );\r
+    HRESULT MoveLast ( );\r
+    HRESULT Open (\r
+        const _variant_t & Source,\r
+        const _variant_t & ActiveConnection,\r
+        enum CursorTypeEnum CursorType,\r
+        enum LockTypeEnum LockType,\r
+        long Options );\r
+    HRESULT Requery (\r
+        long Options );\r
+    HRESULT _xResync (\r
+        enum AffectEnum AffectRecords );\r
+    HRESULT Update (\r
+        const _variant_t & Fields = vtMissing,\r
+        const _variant_t & Values = vtMissing );\r
+    enum PositionEnum GetAbsolutePage ( );\r
+    void PutAbsolutePage (\r
+        enum PositionEnum pl );\r
+    enum EditModeEnum GetEditMode ( );\r
+    _variant_t GetFilter ( );\r
+    void PutFilter (\r
+        const _variant_t & Criteria );\r
+    long GetPageCount ( );\r
+    long GetPageSize ( );\r
+    void PutPageSize (\r
+        long pl );\r
+    _bstr_t GetSort ( );\r
+    void PutSort (\r
+        _bstr_t Criteria );\r
+    long GetStatus ( );\r
+    long GetState ( );\r
+    _RecordsetPtr _xClone ( );\r
+    HRESULT UpdateBatch (\r
+        enum AffectEnum AffectRecords );\r
+    HRESULT CancelBatch (\r
+        enum AffectEnum AffectRecords );\r
+    enum CursorLocationEnum GetCursorLocation ( );\r
+    void PutCursorLocation (\r
+        enum CursorLocationEnum plCursorLoc );\r
+    _RecordsetPtr NextRecordset (\r
+        VARIANT * RecordsAffected );\r
+    VARIANT_BOOL Supports (\r
+        enum CursorOptionEnum CursorOptions );\r
+    _variant_t GetCollect (\r
+        const _variant_t & Index );\r
+    void PutCollect (\r
+        const _variant_t & Index,\r
+        const _variant_t & pvar );\r
+    enum MarshalOptionsEnum GetMarshalOptions ( );\r
+    void PutMarshalOptions (\r
+        enum MarshalOptionsEnum peMarshal );\r
+    HRESULT Find (\r
+        _bstr_t Criteria,\r
+        long SkipRecords,\r
+        enum SearchDirectionEnum SearchDirection,\r
+        const _variant_t & Start = vtMissing );\r
+\r
+    //\r
+    // Raw methods provided by interface\r
+    //\r
+\r
+    virtual HRESULT __stdcall get_AbsolutePosition (\r
+        enum PositionEnum * pl ) = 0;\r
+    virtual HRESULT __stdcall put_AbsolutePosition (\r
+        enum PositionEnum pl ) = 0;\r
+    virtual HRESULT __stdcall putref_ActiveConnection (\r
+        IDispatch * pvar ) = 0;\r
+    virtual HRESULT __stdcall put_ActiveConnection (\r
+        VARIANT pvar ) = 0;\r
+    virtual HRESULT __stdcall get_ActiveConnection (\r
+        VARIANT * pvar ) = 0;\r
+    virtual HRESULT __stdcall get_BOF (\r
+        VARIANT_BOOL * pb ) = 0;\r
+    virtual HRESULT __stdcall get_Bookmark (\r
+        VARIANT * pvBookmark ) = 0;\r
+    virtual HRESULT __stdcall put_Bookmark (\r
+        VARIANT pvBookmark ) = 0;\r
+    virtual HRESULT __stdcall get_CacheSize (\r
+        long * pl ) = 0;\r
+    virtual HRESULT __stdcall put_CacheSize (\r
+        long pl ) = 0;\r
+    virtual HRESULT __stdcall get_CursorType (\r
+        enum CursorTypeEnum * plCursorType ) = 0;\r
+    virtual HRESULT __stdcall put_CursorType (\r
+        enum CursorTypeEnum plCursorType ) = 0;\r
+    virtual HRESULT __stdcall get_adoEOF (\r
+        VARIANT_BOOL * pb ) = 0;\r
+    virtual HRESULT __stdcall get_Fields (\r
+        struct Fields * * ppvObject ) = 0;\r
+    virtual HRESULT __stdcall get_LockType (\r
+        enum LockTypeEnum * plLockType ) = 0;\r
+    virtual HRESULT __stdcall put_LockType (\r
+        enum LockTypeEnum plLockType ) = 0;\r
+    virtual HRESULT __stdcall get_MaxRecords (\r
+        long * plMaxRecords ) = 0;\r
+    virtual HRESULT __stdcall put_MaxRecords (\r
+        long plMaxRecords ) = 0;\r
+    virtual HRESULT __stdcall get_RecordCount (\r
+        long * pl ) = 0;\r
+    virtual HRESULT __stdcall putref_Source (\r
+        IDispatch * pvSource ) = 0;\r
+    virtual HRESULT __stdcall put_Source (\r
+        BSTR pvSource ) = 0;\r
+    virtual HRESULT __stdcall get_Source (\r
+        VARIANT * pvSource ) = 0;\r
+    virtual HRESULT __stdcall raw_AddNew (\r
+        VARIANT FieldList = vtMissing,\r
+        VARIANT Values = vtMissing ) = 0;\r
+    virtual HRESULT __stdcall raw_CancelUpdate ( ) = 0;\r
+    virtual HRESULT __stdcall raw_Close ( ) = 0;\r
+    virtual HRESULT __stdcall raw_Delete (\r
+        enum AffectEnum AffectRecords ) = 0;\r
+    virtual HRESULT __stdcall raw_GetRows (\r
+        long Rows,\r
+        VARIANT Start,\r
+        VARIANT Fields,\r
+        VARIANT * pvar ) = 0;\r
+    virtual HRESULT __stdcall raw_Move (\r
+        long NumRecords,\r
+        VARIANT Start = vtMissing ) = 0;\r
+    virtual HRESULT __stdcall raw_MoveNext ( ) = 0;\r
+    virtual HRESULT __stdcall raw_MovePrevious ( ) = 0;\r
+    virtual HRESULT __stdcall raw_MoveFirst ( ) = 0;\r
+    virtual HRESULT __stdcall raw_MoveLast ( ) = 0;\r
+    virtual HRESULT __stdcall raw_Open (\r
+        VARIANT Source,\r
+        VARIANT ActiveConnection,\r
+        enum CursorTypeEnum CursorType,\r
+        enum LockTypeEnum LockType,\r
+        long Options ) = 0;\r
+    virtual HRESULT __stdcall raw_Requery (\r
+        long Options ) = 0;\r
+    virtual HRESULT __stdcall raw__xResync (\r
+        enum AffectEnum AffectRecords ) = 0;\r
+    virtual HRESULT __stdcall raw_Update (\r
+        VARIANT Fields = vtMissing,\r
+        VARIANT Values = vtMissing ) = 0;\r
+    virtual HRESULT __stdcall get_AbsolutePage (\r
+        enum PositionEnum * pl ) = 0;\r
+    virtual HRESULT __stdcall put_AbsolutePage (\r
+        enum PositionEnum pl ) = 0;\r
+    virtual HRESULT __stdcall get_EditMode (\r
+        enum EditModeEnum * pl ) = 0;\r
+    virtual HRESULT __stdcall get_Filter (\r
+        VARIANT * Criteria ) = 0;\r
+    virtual HRESULT __stdcall put_Filter (\r
+        VARIANT Criteria ) = 0;\r
+    virtual HRESULT __stdcall get_PageCount (\r
+        long * pl ) = 0;\r
+    virtual HRESULT __stdcall get_PageSize (\r
+        long * pl ) = 0;\r
+    virtual HRESULT __stdcall put_PageSize (\r
+        long pl ) = 0;\r
+    virtual HRESULT __stdcall get_Sort (\r
+        BSTR * Criteria ) = 0;\r
+    virtual HRESULT __stdcall put_Sort (\r
+        BSTR Criteria ) = 0;\r
+    virtual HRESULT __stdcall get_Status (\r
+        long * pl ) = 0;\r
+    virtual HRESULT __stdcall get_State (\r
+        long * plObjState ) = 0;\r
+    virtual HRESULT __stdcall raw__xClone (\r
+        struct _Recordset * * ppvObject ) = 0;\r
+    virtual HRESULT __stdcall raw_UpdateBatch (\r
+        enum AffectEnum AffectRecords ) = 0;\r
+    virtual HRESULT __stdcall raw_CancelBatch (\r
+        enum AffectEnum AffectRecords ) = 0;\r
+    virtual HRESULT __stdcall get_CursorLocation (\r
+        enum CursorLocationEnum * plCursorLoc ) = 0;\r
+    virtual HRESULT __stdcall put_CursorLocation (\r
+        enum CursorLocationEnum plCursorLoc ) = 0;\r
+    virtual HRESULT __stdcall raw_NextRecordset (\r
+        VARIANT * RecordsAffected,\r
+        struct _Recordset * * ppiRs ) = 0;\r
+    virtual HRESULT __stdcall raw_Supports (\r
+        enum CursorOptionEnum CursorOptions,\r
+        VARIANT_BOOL * pb ) = 0;\r
+    virtual HRESULT __stdcall get_Collect (\r
+        VARIANT Index,\r
+        VARIANT * pvar ) = 0;\r
+    virtual HRESULT __stdcall put_Collect (\r
+        VARIANT Index,\r
+        VARIANT pvar ) = 0;\r
+    virtual HRESULT __stdcall get_MarshalOptions (\r
+        enum MarshalOptionsEnum * peMarshal ) = 0;\r
+    virtual HRESULT __stdcall put_MarshalOptions (\r
+        enum MarshalOptionsEnum peMarshal ) = 0;\r
+    virtual HRESULT __stdcall raw_Find (\r
+        BSTR Criteria,\r
+        long SkipRecords,\r
+        enum SearchDirectionEnum SearchDirection,\r
+        VARIANT Start = vtMissing ) = 0;\r
+};\r
+\r
+struct __declspec(uuid("0000054f-0000-0010-8000-00aa006d2ea4"))\r
+Recordset20 : Recordset15\r
+{\r
+    //\r
+    // Property data\r
+    //\r
+\r
+    __declspec(property(get=GetDataSource,put=PutRefDataSource))\r
+    IUnknownPtr DataSource;\r
+    __declspec(property(get=GetActiveCommand))\r
+    IDispatchPtr ActiveCommand;\r
+    __declspec(property(get=GetStayInSync,put=PutStayInSync))\r
+    VARIANT_BOOL StayInSync;\r
+    __declspec(property(get=GetDataMember,put=PutDataMember))\r
+    _bstr_t DataMember;\r
+\r
+    //\r
+    // Wrapper methods for error-handling\r
+    //\r
+\r
+    HRESULT Cancel ( );\r
+    IUnknownPtr GetDataSource ( );\r
+    void PutRefDataSource (\r
+        IUnknown * ppunkDataSource );\r
+    HRESULT _xSave (\r
+        _bstr_t FileName,\r
+        enum PersistFormatEnum PersistFormat );\r
+    IDispatchPtr GetActiveCommand ( );\r
+    void PutStayInSync (\r
+        VARIANT_BOOL pbStayInSync );\r
+    VARIANT_BOOL GetStayInSync ( );\r
+    _bstr_t GetString (\r
+        enum StringFormatEnum StringFormat,\r
+        long NumRows,\r
+        _bstr_t ColumnDelimeter,\r
+        _bstr_t RowDelimeter,\r
+        _bstr_t NullExpr );\r
+    _bstr_t GetDataMember ( );\r
+    void PutDataMember (\r
+        _bstr_t pbstrDataMember );\r
+    enum CompareEnum CompareBookmarks (\r
+        const _variant_t & Bookmark1,\r
+        const _variant_t & Bookmark2 );\r
+    _RecordsetPtr Clone (\r
+        enum LockTypeEnum LockType );\r
+    HRESULT Resync (\r
+        enum AffectEnum AffectRecords,\r
+        enum ResyncEnum ResyncValues );\r
+\r
+    //\r
+    // Raw methods provided by interface\r
+    //\r
+\r
+    virtual HRESULT __stdcall raw_Cancel ( ) = 0;\r
+    virtual HRESULT __stdcall get_DataSource (\r
+        IUnknown * * ppunkDataSource ) = 0;\r
+    virtual HRESULT __stdcall putref_DataSource (\r
+        IUnknown * ppunkDataSource ) = 0;\r
+    virtual HRESULT __stdcall raw__xSave (\r
+        BSTR FileName,\r
+        enum PersistFormatEnum PersistFormat ) = 0;\r
+    virtual HRESULT __stdcall get_ActiveCommand (\r
+        IDispatch * * ppCmd ) = 0;\r
+    virtual HRESULT __stdcall put_StayInSync (\r
+        VARIANT_BOOL pbStayInSync ) = 0;\r
+    virtual HRESULT __stdcall get_StayInSync (\r
+        VARIANT_BOOL * pbStayInSync ) = 0;\r
+    virtual HRESULT __stdcall raw_GetString (\r
+        enum StringFormatEnum StringFormat,\r
+        long NumRows,\r
+        BSTR ColumnDelimeter,\r
+        BSTR RowDelimeter,\r
+        BSTR NullExpr,\r
+        BSTR * pRetString ) = 0;\r
+    virtual HRESULT __stdcall get_DataMember (\r
+        BSTR * pbstrDataMember ) = 0;\r
+    virtual HRESULT __stdcall put_DataMember (\r
+        BSTR pbstrDataMember ) = 0;\r
+    virtual HRESULT __stdcall raw_CompareBookmarks (\r
+        VARIANT Bookmark1,\r
+        VARIANT Bookmark2,\r
+        enum CompareEnum * pCompare ) = 0;\r
+    virtual HRESULT __stdcall raw_Clone (\r
+        enum LockTypeEnum LockType,\r
+        struct _Recordset * * ppvObject ) = 0;\r
+    virtual HRESULT __stdcall raw_Resync (\r
+        enum AffectEnum AffectRecords,\r
+        enum ResyncEnum ResyncValues ) = 0;\r
+};\r
+\r
+struct __declspec(uuid("00000555-0000-0010-8000-00aa006d2ea4"))\r
+Recordset21 : Recordset20\r
+{\r
+    //\r
+    // Property data\r
+    //\r
+\r
+    __declspec(property(get=GetIndex,put=PutIndex))\r
+    _bstr_t Index;\r
+\r
+    //\r
+    // Wrapper methods for error-handling\r
+    //\r
+\r
+    HRESULT Seek (\r
+        const _variant_t & KeyValues,\r
+        enum SeekEnum SeekOption );\r
+    void PutIndex (\r
+        _bstr_t pbstrIndex );\r
+    _bstr_t GetIndex ( );\r
+\r
+    //\r
+    // Raw methods provided by interface\r
+    //\r
+\r
+    virtual HRESULT __stdcall raw_Seek (\r
+        VARIANT KeyValues,\r
+        enum SeekEnum SeekOption ) = 0;\r
+    virtual HRESULT __stdcall put_Index (\r
+        BSTR pbstrIndex ) = 0;\r
+    virtual HRESULT __stdcall get_Index (\r
+        BSTR * pbstrIndex ) = 0;\r
+};\r
+\r
+struct __declspec(uuid("00000556-0000-0010-8000-00aa006d2ea4"))\r
+_Recordset : Recordset21\r
+{\r
+    //\r
+    // Wrapper methods for error-handling\r
+    //\r
+\r
+    HRESULT Save (\r
+        const _variant_t & Destination,\r
+        enum PersistFormatEnum PersistFormat );\r
+\r
+    //\r
+    // Raw methods provided by interface\r
+    //\r
+\r
+    virtual HRESULT __stdcall raw_Save (\r
+        VARIANT Destination,\r
+        enum PersistFormatEnum PersistFormat ) = 0;\r
+};\r
+\r
+struct __declspec(uuid("00000506-0000-0010-8000-00aa006d2ea4"))\r
+Fields15 : _Collection\r
+{\r
+    //\r
+    // Property data\r
+    //\r
+\r
+    __declspec(property(get=GetItem))\r
+    FieldPtr Item[];\r
+\r
+    //\r
+    // Wrapper methods for error-handling\r
+    //\r
+\r
+    FieldPtr GetItem (\r
+        const _variant_t & Index );\r
+\r
+    //\r
+    // Raw methods provided by interface\r
+    //\r
+\r
+    virtual HRESULT __stdcall get_Item (\r
+        VARIANT Index,\r
+        struct Field * * ppvObject ) = 0;\r
+};\r
+\r
+struct __declspec(uuid("0000054d-0000-0010-8000-00aa006d2ea4"))\r
+Fields20 : Fields15\r
+{\r
+    //\r
+    // Wrapper methods for error-handling\r
+    //\r
+\r
+    HRESULT _Append (\r
+        _bstr_t Name,\r
+        enum DataTypeEnum Type,\r
+        long DefinedSize,\r
+        enum FieldAttributeEnum Attrib );\r
+    HRESULT Delete (\r
+        const _variant_t & Index );\r
+\r
+    //\r
+    // Raw methods provided by interface\r
+    //\r
+\r
+    virtual HRESULT __stdcall raw__Append (\r
+        BSTR Name,\r
+        enum DataTypeEnum Type,\r
+        long DefinedSize,\r
+        enum FieldAttributeEnum Attrib ) = 0;\r
+    virtual HRESULT __stdcall raw_Delete (\r
+        VARIANT Index ) = 0;\r
+};\r
+\r
+struct __declspec(uuid("00000564-0000-0010-8000-00aa006d2ea4"))\r
+Fields : Fields20\r
+{\r
+    //\r
+    // Wrapper methods for error-handling\r
+    //\r
+\r
+    HRESULT Append (\r
+        _bstr_t Name,\r
+        enum DataTypeEnum Type,\r
+        long DefinedSize,\r
+        enum FieldAttributeEnum Attrib,\r
+        const _variant_t & FieldValue = vtMissing );\r
+    HRESULT Update ( );\r
+    HRESULT Resync (\r
+        enum ResyncEnum ResyncValues );\r
+    HRESULT CancelUpdate ( );\r
+\r
+    //\r
+    // Raw methods provided by interface\r
+    //\r
+\r
+    virtual HRESULT __stdcall raw_Append (\r
+        BSTR Name,\r
+        enum DataTypeEnum Type,\r
+        long DefinedSize,\r
+        enum FieldAttributeEnum Attrib,\r
+        VARIANT FieldValue = vtMissing ) = 0;\r
+    virtual HRESULT __stdcall raw_Update ( ) = 0;\r
+    virtual HRESULT __stdcall raw_Resync (\r
+        enum ResyncEnum ResyncValues ) = 0;\r
+    virtual HRESULT __stdcall raw_CancelUpdate ( ) = 0;\r
+};\r
+\r
+struct __declspec(uuid("0000054c-0000-0010-8000-00aa006d2ea4"))\r
+Field20 : _ADO\r
+{\r
+    //\r
+    // Property data\r
+    //\r
+\r
+    __declspec(property(get=GetValue,put=PutValue))\r
+    _variant_t Value;\r
+    __declspec(property(get=GetName))\r
+    _bstr_t Name;\r
+    __declspec(property(get=GetType,put=PutType))\r
+    enum DataTypeEnum Type;\r
+    __declspec(property(get=GetDefinedSize,put=PutDefinedSize))\r
+    long DefinedSize;\r
+    __declspec(property(get=GetOriginalValue))\r
+    _variant_t OriginalValue;\r
+    __declspec(property(get=GetUnderlyingValue))\r
+    _variant_t UnderlyingValue;\r
+    __declspec(property(get=GetActualSize))\r
+    long ActualSize;\r
+    __declspec(property(get=GetPrecision,put=PutPrecision))\r
+    unsigned char Precision;\r
+    __declspec(property(get=GetNumericScale,put=PutNumericScale))\r
+    unsigned char NumericScale;\r
+    __declspec(property(get=GetAttributes,put=PutAttributes))\r
+    long Attributes;\r
+    __declspec(property(get=GetDataFormat,put=PutRefDataFormat))\r
+    IUnknownPtr DataFormat;\r
+\r
+    //\r
+    // Wrapper methods for error-handling\r
+    //\r
+\r
+    long GetActualSize ( );\r
+    long GetAttributes ( );\r
+    long GetDefinedSize ( );\r
+    _bstr_t GetName ( );\r
+    enum DataTypeEnum GetType ( );\r
+    _variant_t GetValue ( );\r
+    void PutValue (\r
+        const _variant_t & pvar );\r
+    unsigned char GetPrecision ( );\r
+    unsigned char GetNumericScale ( );\r
+    HRESULT AppendChunk (\r
+        const _variant_t & Data );\r
+    _variant_t GetChunk (\r
+        long Length );\r
+    _variant_t GetOriginalValue ( );\r
+    _variant_t GetUnderlyingValue ( );\r
+    IUnknownPtr GetDataFormat ( );\r
+    void PutRefDataFormat (\r
+        IUnknown * ppiDF );\r
+    void PutPrecision (\r
+        unsigned char pbPrecision );\r
+    void PutNumericScale (\r
+        unsigned char pbNumericScale );\r
+    void PutType (\r
+        enum DataTypeEnum pDataType );\r
+    void PutDefinedSize (\r
+        long pl );\r
+    void PutAttributes (\r
+        long pl );\r
+\r
+    //\r
+    // Raw methods provided by interface\r
+    //\r
+\r
+    virtual HRESULT __stdcall get_ActualSize (\r
+        long * pl ) = 0;\r
+    virtual HRESULT __stdcall get_Attributes (\r
+        long * pl ) = 0;\r
+    virtual HRESULT __stdcall get_DefinedSize (\r
+        long * pl ) = 0;\r
+    virtual HRESULT __stdcall get_Name (\r
+        BSTR * pbstr ) = 0;\r
+    virtual HRESULT __stdcall get_Type (\r
+        enum DataTypeEnum * pDataType ) = 0;\r
+    virtual HRESULT __stdcall get_Value (\r
+        VARIANT * pvar ) = 0;\r
+    virtual HRESULT __stdcall put_Value (\r
+        VARIANT pvar ) = 0;\r
+    virtual HRESULT __stdcall get_Precision (\r
+        unsigned char * pbPrecision ) = 0;\r
+    virtual HRESULT __stdcall get_NumericScale (\r
+        unsigned char * pbNumericScale ) = 0;\r
+    virtual HRESULT __stdcall raw_AppendChunk (\r
+        VARIANT Data ) = 0;\r
+    virtual HRESULT __stdcall raw_GetChunk (\r
+        long Length,\r
+        VARIANT * pvar ) = 0;\r
+    virtual HRESULT __stdcall get_OriginalValue (\r
+        VARIANT * pvar ) = 0;\r
+    virtual HRESULT __stdcall get_UnderlyingValue (\r
+        VARIANT * pvar ) = 0;\r
+    virtual HRESULT __stdcall get_DataFormat (\r
+        IUnknown * * ppiDF ) = 0;\r
+    virtual HRESULT __stdcall putref_DataFormat (\r
+        IUnknown * ppiDF ) = 0;\r
+    virtual HRESULT __stdcall put_Precision (\r
+        unsigned char pbPrecision ) = 0;\r
+    virtual HRESULT __stdcall put_NumericScale (\r
+        unsigned char pbNumericScale ) = 0;\r
+    virtual HRESULT __stdcall put_Type (\r
+        enum DataTypeEnum pDataType ) = 0;\r
+    virtual HRESULT __stdcall put_DefinedSize (\r
+        long pl ) = 0;\r
+    virtual HRESULT __stdcall put_Attributes (\r
+        long pl ) = 0;\r
+};\r
+\r
+struct __declspec(uuid("00000569-0000-0010-8000-00aa006d2ea4"))\r
+Field : Field20\r
+{\r
+    //\r
+    // Property data\r
+    //\r
+\r
+    __declspec(property(get=GetStatus))\r
+    long Status;\r
+\r
+    //\r
+    // Wrapper methods for error-handling\r
+    //\r
+\r
+    long GetStatus ( );\r
+\r
+    //\r
+    // Raw methods provided by interface\r
+    //\r
+\r
+    virtual HRESULT __stdcall get_Status (\r
+        long * pFStatus ) = 0;\r
+};\r
+\r
+struct __declspec(uuid("0000050c-0000-0010-8000-00aa006d2ea4"))\r
+_Parameter : _ADO\r
+{\r
+    //\r
+    // Property data\r
+    //\r
+\r
+    __declspec(property(get=GetValue,put=PutValue))\r
+    _variant_t Value;\r
+    __declspec(property(get=GetName,put=PutName))\r
+    _bstr_t Name;\r
+    __declspec(property(get=GetType,put=PutType))\r
+    enum DataTypeEnum Type;\r
+    __declspec(property(get=GetDirection,put=PutDirection))\r
+    enum ParameterDirectionEnum Direction;\r
+    __declspec(property(get=GetPrecision,put=PutPrecision))\r
+    unsigned char Precision;\r
+    __declspec(property(get=GetNumericScale,put=PutNumericScale))\r
+    unsigned char NumericScale;\r
+    __declspec(property(get=GetSize,put=PutSize))\r
+    long Size;\r
+    __declspec(property(get=GetAttributes,put=PutAttributes))\r
+    long Attributes;\r
+\r
+    //\r
+    // Wrapper methods for error-handling\r
+    //\r
+\r
+    _bstr_t GetName ( );\r
+    void PutName (\r
+        _bstr_t pbstr );\r
+    _variant_t GetValue ( );\r
+    void PutValue (\r
+        const _variant_t & pvar );\r
+    enum DataTypeEnum GetType ( );\r
+    void PutType (\r
+        enum DataTypeEnum psDataType );\r
+    void PutDirection (\r
+        enum ParameterDirectionEnum plParmDirection );\r
+    enum ParameterDirectionEnum GetDirection ( );\r
+    void PutPrecision (\r
+        unsigned char pbPrecision );\r
+    unsigned char GetPrecision ( );\r
+    void PutNumericScale (\r
+        unsigned char pbScale );\r
+    unsigned char GetNumericScale ( );\r
+    void PutSize (\r
+        long pl );\r
+    long GetSize ( );\r
+    HRESULT AppendChunk (\r
+        const _variant_t & Val );\r
+    long GetAttributes ( );\r
+    void PutAttributes (\r
+        long plParmAttribs );\r
+\r
+    //\r
+    // Raw methods provided by interface\r
+    //\r
+\r
+    virtual HRESULT __stdcall get_Name (\r
+        BSTR * pbstr ) = 0;\r
+    virtual HRESULT __stdcall put_Name (\r
+        BSTR pbstr ) = 0;\r
+    virtual HRESULT __stdcall get_Value (\r
+        VARIANT * pvar ) = 0;\r
+    virtual HRESULT __stdcall put_Value (\r
+        VARIANT pvar ) = 0;\r
+    virtual HRESULT __stdcall get_Type (\r
+        enum DataTypeEnum * psDataType ) = 0;\r
+    virtual HRESULT __stdcall put_Type (\r
+        enum DataTypeEnum psDataType ) = 0;\r
+    virtual HRESULT __stdcall put_Direction (\r
+        enum ParameterDirectionEnum plParmDirection ) = 0;\r
+    virtual HRESULT __stdcall get_Direction (\r
+        enum ParameterDirectionEnum * plParmDirection ) = 0;\r
+    virtual HRESULT __stdcall put_Precision (\r
+        unsigned char pbPrecision ) = 0;\r
+    virtual HRESULT __stdcall get_Precision (\r
+        unsigned char * pbPrecision ) = 0;\r
+    virtual HRESULT __stdcall put_NumericScale (\r
+        unsigned char pbScale ) = 0;\r
+    virtual HRESULT __stdcall get_NumericScale (\r
+        unsigned char * pbScale ) = 0;\r
+    virtual HRESULT __stdcall put_Size (\r
+        long pl ) = 0;\r
+    virtual HRESULT __stdcall get_Size (\r
+        long * pl ) = 0;\r
+    virtual HRESULT __stdcall raw_AppendChunk (\r
+        VARIANT Val ) = 0;\r
+    virtual HRESULT __stdcall get_Attributes (\r
+        long * plParmAttribs ) = 0;\r
+    virtual HRESULT __stdcall put_Attributes (\r
+        long plParmAttribs ) = 0;\r
+};\r
+\r
+struct __declspec(uuid("0000050d-0000-0010-8000-00aa006d2ea4"))\r
+Parameters : _DynaCollection\r
+{\r
+    //\r
+    // Property data\r
+    //\r
+\r
+    __declspec(property(get=GetItem))\r
+    _ParameterPtr Item[];\r
+\r
+    //\r
+    // Wrapper methods for error-handling\r
+    //\r
+\r
+    _ParameterPtr GetItem (\r
+        const _variant_t & Index );\r
+\r
+    //\r
+    // Raw methods provided by interface\r
+    //\r
+\r
+    virtual HRESULT __stdcall get_Item (\r
+        VARIANT Index,\r
+        struct _Parameter * * ppvObject ) = 0;\r
+};\r
+\r
+struct __declspec(uuid("0000054e-0000-0010-8000-00aa006d2ea4"))\r
+_Command : Command15\r
+{\r
+    //\r
+    // Property data\r
+    //\r
+\r
+    __declspec(property(get=GetState))\r
+    long State;\r
+\r
+    //\r
+    // Wrapper methods for error-handling\r
+    //\r
+\r
+    long GetState ( );\r
+    HRESULT Cancel ( );\r
+\r
+    //\r
+    // Raw methods provided by interface\r
+    //\r
+\r
+    virtual HRESULT __stdcall get_State (\r
+        long * plObjState ) = 0;\r
+    virtual HRESULT __stdcall raw_Cancel ( ) = 0;\r
+};\r
+\r
+struct __declspec(uuid("00000402-0000-0010-8000-00aa006d2ea4"))\r
+ConnectionEventsVt : IUnknown\r
+{\r
+    //\r
+    // Wrapper methods for error-handling\r
+    //\r
+\r
+    HRESULT InfoMessage (\r
+        struct Error * pError,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Connection * pConnection );\r
+    HRESULT BeginTransComplete (\r
+        long TransactionLevel,\r
+        struct Error * pError,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Connection * pConnection );\r
+    HRESULT CommitTransComplete (\r
+        struct Error * pError,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Connection * pConnection );\r
+    HRESULT RollbackTransComplete (\r
+        struct Error * pError,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Connection * pConnection );\r
+    HRESULT WillExecute (\r
+        BSTR * Source,\r
+        enum CursorTypeEnum * CursorType,\r
+        enum LockTypeEnum * LockType,\r
+        long * Options,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Command * pCommand,\r
+        struct _Recordset * pRecordset,\r
+        struct _Connection * pConnection );\r
+    HRESULT ExecuteComplete (\r
+        long RecordsAffected,\r
+        struct Error * pError,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Command * pCommand,\r
+        struct _Recordset * pRecordset,\r
+        struct _Connection * pConnection );\r
+    HRESULT WillConnect (\r
+        BSTR * ConnectionString,\r
+        BSTR * UserID,\r
+        BSTR * Password,\r
+        long * Options,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Connection * pConnection );\r
+    HRESULT ConnectComplete (\r
+        struct Error * pError,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Connection * pConnection );\r
+    HRESULT Disconnect (\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Connection * pConnection );\r
+\r
+    //\r
+    // Raw methods provided by interface\r
+    //\r
+\r
+    virtual HRESULT __stdcall raw_InfoMessage (\r
+        struct Error * pError,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Connection * pConnection ) = 0;\r
+    virtual HRESULT __stdcall raw_BeginTransComplete (\r
+        long TransactionLevel,\r
+        struct Error * pError,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Connection * pConnection ) = 0;\r
+    virtual HRESULT __stdcall raw_CommitTransComplete (\r
+        struct Error * pError,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Connection * pConnection ) = 0;\r
+    virtual HRESULT __stdcall raw_RollbackTransComplete (\r
+        struct Error * pError,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Connection * pConnection ) = 0;\r
+    virtual HRESULT __stdcall raw_WillExecute (\r
+        BSTR * Source,\r
+        enum CursorTypeEnum * CursorType,\r
+        enum LockTypeEnum * LockType,\r
+        long * Options,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Command * pCommand,\r
+        struct _Recordset * pRecordset,\r
+        struct _Connection * pConnection ) = 0;\r
+    virtual HRESULT __stdcall raw_ExecuteComplete (\r
+        long RecordsAffected,\r
+        struct Error * pError,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Command * pCommand,\r
+        struct _Recordset * pRecordset,\r
+        struct _Connection * pConnection ) = 0;\r
+    virtual HRESULT __stdcall raw_WillConnect (\r
+        BSTR * ConnectionString,\r
+        BSTR * UserID,\r
+        BSTR * Password,\r
+        long * Options,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Connection * pConnection ) = 0;\r
+    virtual HRESULT __stdcall raw_ConnectComplete (\r
+        struct Error * pError,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Connection * pConnection ) = 0;\r
+    virtual HRESULT __stdcall raw_Disconnect (\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Connection * pConnection ) = 0;\r
+};\r
+\r
+struct __declspec(uuid("00000403-0000-0010-8000-00aa006d2ea4"))\r
+RecordsetEventsVt : IUnknown\r
+{\r
+    //\r
+    // Wrapper methods for error-handling\r
+    //\r
+\r
+    HRESULT WillChangeField (\r
+        long cFields,\r
+        const _variant_t & Fields,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Recordset * pRecordset );\r
+    HRESULT FieldChangeComplete (\r
+        long cFields,\r
+        const _variant_t & Fields,\r
+        struct Error * pError,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Recordset * pRecordset );\r
+    HRESULT WillChangeRecord (\r
+        enum EventReasonEnum adReason,\r
+        long cRecords,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Recordset * pRecordset );\r
+    HRESULT RecordChangeComplete (\r
+        enum EventReasonEnum adReason,\r
+        long cRecords,\r
+        struct Error * pError,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Recordset * pRecordset );\r
+    HRESULT WillChangeRecordset (\r
+        enum EventReasonEnum adReason,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Recordset * pRecordset );\r
+    HRESULT RecordsetChangeComplete (\r
+        enum EventReasonEnum adReason,\r
+        struct Error * pError,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Recordset * pRecordset );\r
+    HRESULT WillMove (\r
+        enum EventReasonEnum adReason,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Recordset * pRecordset );\r
+    HRESULT MoveComplete (\r
+        enum EventReasonEnum adReason,\r
+        struct Error * pError,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Recordset * pRecordset );\r
+    HRESULT EndOfRecordset (\r
+        VARIANT_BOOL * fMoreData,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Recordset * pRecordset );\r
+    HRESULT FetchProgress (\r
+        long Progress,\r
+        long MaxProgress,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Recordset * pRecordset );\r
+    HRESULT FetchComplete (\r
+        struct Error * pError,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Recordset * pRecordset );\r
+\r
+    //\r
+    // Raw methods provided by interface\r
+    //\r
+\r
+    virtual HRESULT __stdcall raw_WillChangeField (\r
+        long cFields,\r
+        VARIANT Fields,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Recordset * pRecordset ) = 0;\r
+    virtual HRESULT __stdcall raw_FieldChangeComplete (\r
+        long cFields,\r
+        VARIANT Fields,\r
+        struct Error * pError,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Recordset * pRecordset ) = 0;\r
+    virtual HRESULT __stdcall raw_WillChangeRecord (\r
+        enum EventReasonEnum adReason,\r
+        long cRecords,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Recordset * pRecordset ) = 0;\r
+    virtual HRESULT __stdcall raw_RecordChangeComplete (\r
+        enum EventReasonEnum adReason,\r
+        long cRecords,\r
+        struct Error * pError,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Recordset * pRecordset ) = 0;\r
+    virtual HRESULT __stdcall raw_WillChangeRecordset (\r
+        enum EventReasonEnum adReason,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Recordset * pRecordset ) = 0;\r
+    virtual HRESULT __stdcall raw_RecordsetChangeComplete (\r
+        enum EventReasonEnum adReason,\r
+        struct Error * pError,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Recordset * pRecordset ) = 0;\r
+    virtual HRESULT __stdcall raw_WillMove (\r
+        enum EventReasonEnum adReason,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Recordset * pRecordset ) = 0;\r
+    virtual HRESULT __stdcall raw_MoveComplete (\r
+        enum EventReasonEnum adReason,\r
+        struct Error * pError,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Recordset * pRecordset ) = 0;\r
+    virtual HRESULT __stdcall raw_EndOfRecordset (\r
+        VARIANT_BOOL * fMoreData,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Recordset * pRecordset ) = 0;\r
+    virtual HRESULT __stdcall raw_FetchProgress (\r
+        long Progress,\r
+        long MaxProgress,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Recordset * pRecordset ) = 0;\r
+    virtual HRESULT __stdcall raw_FetchComplete (\r
+        struct Error * pError,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Recordset * pRecordset ) = 0;\r
+};\r
+\r
+struct __declspec(uuid("00000400-0000-0010-8000-00aa006d2ea4"))\r
+ConnectionEvents : IDispatch\r
+{\r
+    //\r
+    // Wrapper methods for error-handling\r
+    //\r
+\r
+    // Methods:\r
+    HRESULT InfoMessage (\r
+        struct Error * pError,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Connection * pConnection );\r
+    HRESULT BeginTransComplete (\r
+        long TransactionLevel,\r
+        struct Error * pError,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Connection * pConnection );\r
+    HRESULT CommitTransComplete (\r
+        struct Error * pError,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Connection * pConnection );\r
+    HRESULT RollbackTransComplete (\r
+        struct Error * pError,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Connection * pConnection );\r
+    HRESULT WillExecute (\r
+        BSTR * Source,\r
+        enum CursorTypeEnum * CursorType,\r
+        enum LockTypeEnum * LockType,\r
+        long * Options,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Command * pCommand,\r
+        struct _Recordset * pRecordset,\r
+        struct _Connection * pConnection );\r
+    HRESULT ExecuteComplete (\r
+        long RecordsAffected,\r
+        struct Error * pError,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Command * pCommand,\r
+        struct _Recordset * pRecordset,\r
+        struct _Connection * pConnection );\r
+    HRESULT WillConnect (\r
+        BSTR * ConnectionString,\r
+        BSTR * UserID,\r
+        BSTR * Password,\r
+        long * Options,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Connection * pConnection );\r
+    HRESULT ConnectComplete (\r
+        struct Error * pError,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Connection * pConnection );\r
+    HRESULT Disconnect (\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Connection * pConnection );\r
+};\r
+\r
+struct __declspec(uuid("00000266-0000-0010-8000-00aa006d2ea4"))\r
+RecordsetEvents : IDispatch\r
+{\r
+    //\r
+    // Wrapper methods for error-handling\r
+    //\r
+\r
+    // Methods:\r
+    HRESULT WillChangeField (\r
+        long cFields,\r
+        const _variant_t & Fields,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Recordset * pRecordset );\r
+    HRESULT FieldChangeComplete (\r
+        long cFields,\r
+        const _variant_t & Fields,\r
+        struct Error * pError,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Recordset * pRecordset );\r
+    HRESULT WillChangeRecord (\r
+        enum EventReasonEnum adReason,\r
+        long cRecords,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Recordset * pRecordset );\r
+    HRESULT RecordChangeComplete (\r
+        enum EventReasonEnum adReason,\r
+        long cRecords,\r
+        struct Error * pError,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Recordset * pRecordset );\r
+    HRESULT WillChangeRecordset (\r
+        enum EventReasonEnum adReason,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Recordset * pRecordset );\r
+    HRESULT RecordsetChangeComplete (\r
+        enum EventReasonEnum adReason,\r
+        struct Error * pError,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Recordset * pRecordset );\r
+    HRESULT WillMove (\r
+        enum EventReasonEnum adReason,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Recordset * pRecordset );\r
+    HRESULT MoveComplete (\r
+        enum EventReasonEnum adReason,\r
+        struct Error * pError,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Recordset * pRecordset );\r
+    HRESULT EndOfRecordset (\r
+        VARIANT_BOOL * fMoreData,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Recordset * pRecordset );\r
+    HRESULT FetchProgress (\r
+        long Progress,\r
+        long MaxProgress,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Recordset * pRecordset );\r
+    HRESULT FetchComplete (\r
+        struct Error * pError,\r
+        enum EventStatusEnum * adStatus,\r
+        struct _Recordset * pRecordset );\r
+};\r
+\r
+struct __declspec(uuid("00000516-0000-0010-8000-00aa006d2ea4"))\r
+ADOConnectionConstruction15 : IUnknown\r
+{\r
+    //\r
+    // Property data\r
+    //\r
+\r
+    __declspec(property(get=GetDSO))\r
+    IUnknownPtr DSO;\r
+    __declspec(property(get=GetSession))\r
+    IUnknownPtr Session;\r
+\r
+    //\r
+    // Wrapper methods for error-handling\r
+    //\r
+\r
+    IUnknownPtr GetDSO ( );\r
+    IUnknownPtr GetSession ( );\r
+    HRESULT WrapDSOandSession (\r
+        IUnknown * pDSO,\r
+        IUnknown * pSession );\r
+\r
+    //\r
+    // Raw methods provided by interface\r
+    //\r
+\r
+    virtual HRESULT __stdcall get_DSO (\r
+        IUnknown * * ppDSO ) = 0;\r
+    virtual HRESULT __stdcall get_Session (\r
+        IUnknown * * ppSession ) = 0;\r
+    virtual HRESULT __stdcall raw_WrapDSOandSession (\r
+        IUnknown * pDSO,\r
+        IUnknown * pSession ) = 0;\r
+};\r
+\r
+struct __declspec(uuid("00000551-0000-0010-8000-00aa006d2ea4"))\r
+ADOConnectionConstruction : ADOConnectionConstruction15\r
+{};\r
+\r
+struct __declspec(uuid("00000514-0000-0010-8000-00aa006d2ea4"))\r
+Connection;\r
+    // [ default ] interface _Connection\r
+    // [ default, source ] dispinterface ConnectionEvents\r
+\r
+struct __declspec(uuid("00000562-0000-0010-8000-00aa006d2ea4"))\r
+_Record : _ADO\r
+{\r
+    //\r
+    // Property data\r
+    //\r
+\r
+    __declspec(property(get=GetFields))\r
+    FieldsPtr Fields;\r
+    __declspec(property(get=GetState))\r
+    enum ObjectStateEnum State;\r
+    __declspec(property(get=GetMode,put=PutMode))\r
+    enum ConnectModeEnum Mode;\r
+    __declspec(property(get=GetParentURL))\r
+    _bstr_t ParentURL;\r
+    __declspec(property(get=GetRecordType))\r
+    enum RecordTypeEnum RecordType;\r
+\r
+    //\r
+    // Wrapper methods for error-handling\r
+    //\r
+\r
+    _variant_t GetActiveConnection ( );\r
+    void PutActiveConnection (\r
+        _bstr_t pvar );\r
+    void PutRefActiveConnection (\r
+        struct _Connection * pvar );\r
+    enum ObjectStateEnum GetState ( );\r
+    _variant_t GetSource ( );\r
+    void PutSource (\r
+        _bstr_t pvar );\r
+    void PutRefSource (\r
+        IDispatch * pvar );\r
+    enum ConnectModeEnum GetMode ( );\r
+    void PutMode (\r
+        enum ConnectModeEnum pMode );\r
+    _bstr_t GetParentURL ( );\r
+    _bstr_t MoveRecord (\r
+        _bstr_t Source,\r
+        _bstr_t Destination,\r
+        _bstr_t UserName,\r
+        _bstr_t Password,\r
+        enum MoveRecordOptionsEnum Options,\r
+        VARIANT_BOOL Async );\r
+    _bstr_t CopyRecord (\r
+        _bstr_t Source,\r
+        _bstr_t Destination,\r
+        _bstr_t UserName,\r
+        _bstr_t Password,\r
+        enum CopyRecordOptionsEnum Options,\r
+        VARIANT_BOOL Async );\r
+    HRESULT DeleteRecord (\r
+        _bstr_t Source,\r
+        VARIANT_BOOL Async );\r
+    HRESULT Open (\r
+        const _variant_t & Source,\r
+        const _variant_t & ActiveConnection,\r
+        enum ConnectModeEnum Mode,\r
+        enum RecordCreateOptionsEnum CreateOptions,\r
+        enum RecordOpenOptionsEnum Options,\r
+        _bstr_t UserName,\r
+        _bstr_t Password );\r
+    HRESULT Close ( );\r
+    FieldsPtr GetFields ( );\r
+    enum RecordTypeEnum GetRecordType ( );\r
+    _RecordsetPtr GetChildren ( );\r
+    HRESULT Cancel ( );\r
+\r
+    //\r
+    // Raw methods provided by interface\r
+    //\r
+\r
+    virtual HRESULT __stdcall get_ActiveConnection (\r
+        VARIANT * pvar ) = 0;\r
+    virtual HRESULT __stdcall put_ActiveConnection (\r
+        BSTR pvar ) = 0;\r
+    virtual HRESULT __stdcall putref_ActiveConnection (\r
+        struct _Connection * pvar ) = 0;\r
+    virtual HRESULT __stdcall get_State (\r
+        enum ObjectStateEnum * pState ) = 0;\r
+    virtual HRESULT __stdcall get_Source (\r
+        VARIANT * pvar ) = 0;\r
+    virtual HRESULT __stdcall put_Source (\r
+        BSTR pvar ) = 0;\r
+    virtual HRESULT __stdcall putref_Source (\r
+        IDispatch * pvar ) = 0;\r
+    virtual HRESULT __stdcall get_Mode (\r
+        enum ConnectModeEnum * pMode ) = 0;\r
+    virtual HRESULT __stdcall put_Mode (\r
+        enum ConnectModeEnum pMode ) = 0;\r
+    virtual HRESULT __stdcall get_ParentURL (\r
+        BSTR * pbstrParentURL ) = 0;\r
+    virtual HRESULT __stdcall raw_MoveRecord (\r
+        BSTR Source,\r
+        BSTR Destination,\r
+        BSTR UserName,\r
+        BSTR Password,\r
+        enum MoveRecordOptionsEnum Options,\r
+        VARIANT_BOOL Async,\r
+        BSTR * pbstrNewURL ) = 0;\r
+    virtual HRESULT __stdcall raw_CopyRecord (\r
+        BSTR Source,\r
+        BSTR Destination,\r
+        BSTR UserName,\r
+        BSTR Password,\r
+        enum CopyRecordOptionsEnum Options,\r
+        VARIANT_BOOL Async,\r
+        BSTR * pbstrNewURL ) = 0;\r
+    virtual HRESULT __stdcall raw_DeleteRecord (\r
+        BSTR Source,\r
+        VARIANT_BOOL Async ) = 0;\r
+    virtual HRESULT __stdcall raw_Open (\r
+        VARIANT Source,\r
+        VARIANT ActiveConnection,\r
+        enum ConnectModeEnum Mode,\r
+        enum RecordCreateOptionsEnum CreateOptions,\r
+        enum RecordOpenOptionsEnum Options,\r
+        BSTR UserName,\r
+        BSTR Password ) = 0;\r
+    virtual HRESULT __stdcall raw_Close ( ) = 0;\r
+    virtual HRESULT __stdcall get_Fields (\r
+        struct Fields * * ppFlds ) = 0;\r
+    virtual HRESULT __stdcall get_RecordType (\r
+        enum RecordTypeEnum * ptype ) = 0;\r
+    virtual HRESULT __stdcall raw_GetChildren (\r
+        struct _Recordset * * pprset ) = 0;\r
+    virtual HRESULT __stdcall raw_Cancel ( ) = 0;\r
+};\r
+\r
+struct __declspec(uuid("00000560-0000-0010-8000-00aa006d2ea4"))\r
+Record;\r
+    // [ default ] interface _Record\r
+\r
+struct __declspec(uuid("00000563-0000-0010-8000-00aa006d2ea4"))\r
+IRecFields : IUnknown\r
+{\r
+    //\r
+    // Wrapper methods for error-handling\r
+    //\r
+\r
+    HRESULT ADOCheck ( );\r
+\r
+    //\r
+    // Raw methods provided by interface\r
+    //\r
+\r
+    virtual HRESULT __stdcall raw_ADOCheck ( ) = 0;\r
+};\r
+\r
+struct __declspec(uuid("00000565-0000-0010-8000-00aa006d2ea4"))\r
+_Stream : IDispatch\r
+{\r
+    //\r
+    // Property data\r
+    //\r
+\r
+    __declspec(property(get=GetSize))\r
+    long Size;\r
+    __declspec(property(get=GetEOS))\r
+    VARIANT_BOOL EOS;\r
+    __declspec(property(get=GetPosition,put=PutPosition))\r
+    long Position;\r
+    __declspec(property(get=GetType,put=PutType))\r
+    enum StreamTypeEnum Type;\r
+    __declspec(property(get=GetLineSeparator,put=PutLineSeparator))\r
+    enum LineSeparatorEnum LineSeparator;\r
+    __declspec(property(get=GetState))\r
+    enum ObjectStateEnum State;\r
+    __declspec(property(get=GetMode,put=PutMode))\r
+    enum ConnectModeEnum Mode;\r
+    __declspec(property(get=GetCharset,put=PutCharset))\r
+    _bstr_t Charset;\r
+\r
+    //\r
+    // Wrapper methods for error-handling\r
+    //\r
+\r
+    long GetSize ( );\r
+    VARIANT_BOOL GetEOS ( );\r
+    long GetPosition ( );\r
+    void PutPosition (\r
+        long pPos );\r
+    enum StreamTypeEnum GetType ( );\r
+    void PutType (\r
+        enum StreamTypeEnum ptype );\r
+    enum LineSeparatorEnum GetLineSeparator ( );\r
+    void PutLineSeparator (\r
+        enum LineSeparatorEnum pLS );\r
+    enum ObjectStateEnum GetState ( );\r
+    enum ConnectModeEnum GetMode ( );\r
+    void PutMode (\r
+        enum ConnectModeEnum pMode );\r
+    _bstr_t GetCharset ( );\r
+    void PutCharset (\r
+        _bstr_t pbstrCharset );\r
+    _variant_t Read (\r
+        long NumBytes );\r
+    HRESULT Open (\r
+        const _variant_t & Source,\r
+        enum ConnectModeEnum Mode,\r
+        enum StreamOpenOptionsEnum Options,\r
+        _bstr_t UserName,\r
+        _bstr_t Password );\r
+    HRESULT Close ( );\r
+    HRESULT SkipLine ( );\r
+    HRESULT Write (\r
+        const _variant_t & Buffer );\r
+    HRESULT SetEOS ( );\r
+    HRESULT CopyTo (\r
+        struct _Stream * DestStream,\r
+        long CharNumber );\r
+    HRESULT Flush ( );\r
+    HRESULT SaveToFile (\r
+        _bstr_t FileName,\r
+        enum SaveOptionsEnum Options );\r
+    HRESULT LoadFromFile (\r
+        _bstr_t FileName );\r
+    _bstr_t ReadText (\r
+        long NumChars );\r
+    HRESULT WriteText (\r
+        _bstr_t Data,\r
+        enum StreamWriteEnum Options );\r
+    HRESULT Cancel ( );\r
+\r
+    //\r
+    // Raw methods provided by interface\r
+    //\r
+\r
+    virtual HRESULT __stdcall get_Size (\r
+        long * pSize ) = 0;\r
+    virtual HRESULT __stdcall get_EOS (\r
+        VARIANT_BOOL * pEOS ) = 0;\r
+    virtual HRESULT __stdcall get_Position (\r
+        long * pPos ) = 0;\r
+    virtual HRESULT __stdcall put_Position (\r
+        long pPos ) = 0;\r
+    virtual HRESULT __stdcall get_Type (\r
+        enum StreamTypeEnum * ptype ) = 0;\r
+    virtual HRESULT __stdcall put_Type (\r
+        enum StreamTypeEnum ptype ) = 0;\r
+    virtual HRESULT __stdcall get_LineSeparator (\r
+        enum LineSeparatorEnum * pLS ) = 0;\r
+    virtual HRESULT __stdcall put_LineSeparator (\r
+        enum LineSeparatorEnum pLS ) = 0;\r
+    virtual HRESULT __stdcall get_State (\r
+        enum ObjectStateEnum * pState ) = 0;\r
+    virtual HRESULT __stdcall get_Mode (\r
+        enum ConnectModeEnum * pMode ) = 0;\r
+    virtual HRESULT __stdcall put_Mode (\r
+        enum ConnectModeEnum pMode ) = 0;\r
+    virtual HRESULT __stdcall get_Charset (\r
+        BSTR * pbstrCharset ) = 0;\r
+    virtual HRESULT __stdcall put_Charset (\r
+        BSTR pbstrCharset ) = 0;\r
+    virtual HRESULT __stdcall raw_Read (\r
+        long NumBytes,\r
+        VARIANT * pval ) = 0;\r
+    virtual HRESULT __stdcall raw_Open (\r
+        VARIANT Source,\r
+        enum ConnectModeEnum Mode,\r
+        enum StreamOpenOptionsEnum Options,\r
+        BSTR UserName,\r
+        BSTR Password ) = 0;\r
+    virtual HRESULT __stdcall raw_Close ( ) = 0;\r
+    virtual HRESULT __stdcall raw_SkipLine ( ) = 0;\r
+    virtual HRESULT __stdcall raw_Write (\r
+        VARIANT Buffer ) = 0;\r
+    virtual HRESULT __stdcall raw_SetEOS ( ) = 0;\r
+    virtual HRESULT __stdcall raw_CopyTo (\r
+        struct _Stream * DestStream,\r
+        long CharNumber ) = 0;\r
+    virtual HRESULT __stdcall raw_Flush ( ) = 0;\r
+    virtual HRESULT __stdcall raw_SaveToFile (\r
+        BSTR FileName,\r
+        enum SaveOptionsEnum Options ) = 0;\r
+    virtual HRESULT __stdcall raw_LoadFromFile (\r
+        BSTR FileName ) = 0;\r
+    virtual HRESULT __stdcall raw_ReadText (\r
+        long NumChars,\r
+        BSTR * pbstr ) = 0;\r
+    virtual HRESULT __stdcall raw_WriteText (\r
+        BSTR Data,\r
+        enum StreamWriteEnum Options ) = 0;\r
+    virtual HRESULT __stdcall raw_Cancel ( ) = 0;\r
+};\r
+\r
+struct __declspec(uuid("00000566-0000-0010-8000-00aa006d2ea4"))\r
+Stream;\r
+    // [ default ] interface _Stream\r
+\r
+struct __declspec(uuid("00000567-0000-0010-8000-00aa006d2ea4"))\r
+ADORecordConstruction : IDispatch\r
+{\r
+    //\r
+    // Property data\r
+    //\r
+\r
+    __declspec(property(get=GetRow,put=PutRow))\r
+    IUnknownPtr Row;\r
+    __declspec(property(put=PutParentRow))\r
+    IUnknownPtr ParentRow;\r
+\r
+    //\r
+    // Wrapper methods for error-handling\r
+    //\r
+\r
+    IUnknownPtr GetRow ( );\r
+    void PutRow (\r
+        IUnknown * ppRow );\r
+    void PutParentRow (\r
+        IUnknown * _arg1 );\r
+\r
+    //\r
+    // Raw methods provided by interface\r
+    //\r
+\r
+    virtual HRESULT __stdcall get_Row (\r
+        IUnknown * * ppRow ) = 0;\r
+    virtual HRESULT __stdcall put_Row (\r
+        IUnknown * ppRow ) = 0;\r
+    virtual HRESULT __stdcall put_ParentRow (\r
+        IUnknown * _arg1 ) = 0;\r
+};\r
+\r
+struct __declspec(uuid("00000568-0000-0010-8000-00aa006d2ea4"))\r
+ADOStreamConstruction : IDispatch\r
+{\r
+    //\r
+    // Property data\r
+    //\r
+\r
+    __declspec(property(get=GetStream,put=PutStream))\r
+    IUnknownPtr Stream;\r
+\r
+    //\r
+    // Wrapper methods for error-handling\r
+    //\r
+\r
+    IUnknownPtr GetStream ( );\r
+    void PutStream (\r
+        IUnknown * ppStm );\r
+\r
+    //\r
+    // Raw methods provided by interface\r
+    //\r
+\r
+    virtual HRESULT __stdcall get_Stream (\r
+        IUnknown * * ppStm ) = 0;\r
+    virtual HRESULT __stdcall put_Stream (\r
+        IUnknown * ppStm ) = 0;\r
+};\r
+\r
+struct __declspec(uuid("00000517-0000-0010-8000-00aa006d2ea4"))\r
+ADOCommandConstruction : IUnknown\r
+{\r
+    //\r
+    // Property data\r
+    //\r
+\r
+    __declspec(property(get=GetOLEDBCommand,put=PutOLEDBCommand))\r
+    IUnknownPtr OLEDBCommand;\r
+\r
+    //\r
+    // Wrapper methods for error-handling\r
+    //\r
+\r
+    IUnknownPtr GetOLEDBCommand ( );\r
+    void PutOLEDBCommand (\r
+        IUnknown * ppOLEDBCommand );\r
+\r
+    //\r
+    // Raw methods provided by interface\r
+    //\r
+\r
+    virtual HRESULT __stdcall get_OLEDBCommand (\r
+        IUnknown * * ppOLEDBCommand ) = 0;\r
+    virtual HRESULT __stdcall put_OLEDBCommand (\r
+        IUnknown * ppOLEDBCommand ) = 0;\r
+};\r
+\r
+struct __declspec(uuid("00000507-0000-0010-8000-00aa006d2ea4"))\r
+Command;\r
+    // [ default ] interface _Command\r
+\r
+struct __declspec(uuid("00000535-0000-0010-8000-00aa006d2ea4"))\r
+Recordset;\r
+    // [ default ] interface _Recordset\r
+    // [ default, source ] dispinterface RecordsetEvents\r
+\r
+struct __declspec(uuid("00000283-0000-0010-8000-00aa006d2ea4"))\r
+ADORecordsetConstruction : IDispatch\r
+{\r
+    //\r
+    // Property data\r
+    //\r
+\r
+    __declspec(property(get=GetRowset,put=PutRowset))\r
+    IUnknownPtr Rowset;\r
+    __declspec(property(get=GetChapter,put=PutChapter))\r
+    long Chapter;\r
+    __declspec(property(get=GetRowPosition,put=PutRowPosition))\r
+    IUnknownPtr RowPosition;\r
+\r
+    //\r
+    // Wrapper methods for error-handling\r
+    //\r
+\r
+    IUnknownPtr GetRowset ( );\r
+    void PutRowset (\r
+        IUnknown * ppRowset );\r
+    long GetChapter ( );\r
+    void PutChapter (\r
+        long plChapter );\r
+    IUnknownPtr GetRowPosition ( );\r
+    void PutRowPosition (\r
+        IUnknown * ppRowPos );\r
+\r
+    //\r
+    // Raw methods provided by interface\r
+    //\r
+\r
+    virtual HRESULT __stdcall get_Rowset (\r
+        IUnknown * * ppRowset ) = 0;\r
+    virtual HRESULT __stdcall put_Rowset (\r
+        IUnknown * ppRowset ) = 0;\r
+    virtual HRESULT __stdcall get_Chapter (\r
+        long * plChapter ) = 0;\r
+    virtual HRESULT __stdcall put_Chapter (\r
+        long plChapter ) = 0;\r
+    virtual HRESULT __stdcall get_RowPosition (\r
+        IUnknown * * ppRowPos ) = 0;\r
+    virtual HRESULT __stdcall put_RowPosition (\r
+        IUnknown * ppRowPos ) = 0;\r
+};\r
+\r
+struct __declspec(uuid("00000505-0000-0010-8000-00aa006d2ea4"))\r
+Field15 : _ADO\r
+{\r
+    //\r
+    // Property data\r
+    //\r
+\r
+    __declspec(property(get=GetValue,put=PutValue))\r
+    _variant_t Value;\r
+    __declspec(property(get=GetName))\r
+    _bstr_t Name;\r
+    __declspec(property(get=GetType))\r
+    enum DataTypeEnum Type;\r
+    __declspec(property(get=GetDefinedSize))\r
+    long DefinedSize;\r
+    __declspec(property(get=GetOriginalValue))\r
+    _variant_t OriginalValue;\r
+    __declspec(property(get=GetUnderlyingValue))\r
+    _variant_t UnderlyingValue;\r
+    __declspec(property(get=GetActualSize))\r
+    long ActualSize;\r
+    __declspec(property(get=GetPrecision))\r
+    unsigned char Precision;\r
+    __declspec(property(get=GetNumericScale))\r
+    unsigned char NumericScale;\r
+    __declspec(property(get=GetAttributes))\r
+    long Attributes;\r
+\r
+    //\r
+    // Wrapper methods for error-handling\r
+    //\r
+\r
+    long GetActualSize ( );\r
+    long GetAttributes ( );\r
+    long GetDefinedSize ( );\r
+    _bstr_t GetName ( );\r
+    enum DataTypeEnum GetType ( );\r
+    _variant_t GetValue ( );\r
+    void PutValue (\r
+        const _variant_t & pvar );\r
+    unsigned char GetPrecision ( );\r
+    unsigned char GetNumericScale ( );\r
+    HRESULT AppendChunk (\r
+        const _variant_t & Data );\r
+    _variant_t GetChunk (\r
+        long Length );\r
+    _variant_t GetOriginalValue ( );\r
+    _variant_t GetUnderlyingValue ( );\r
+\r
+    //\r
+    // Raw methods provided by interface\r
+    //\r
+\r
+    virtual HRESULT __stdcall get_ActualSize (\r
+        long * pl ) = 0;\r
+    virtual HRESULT __stdcall get_Attributes (\r
+        long * pl ) = 0;\r
+    virtual HRESULT __stdcall get_DefinedSize (\r
+        long * pl ) = 0;\r
+    virtual HRESULT __stdcall get_Name (\r
+        BSTR * pbstr ) = 0;\r
+    virtual HRESULT __stdcall get_Type (\r
+        enum DataTypeEnum * pDataType ) = 0;\r
+    virtual HRESULT __stdcall get_Value (\r
+        VARIANT * pvar ) = 0;\r
+    virtual HRESULT __stdcall put_Value (\r
+        VARIANT pvar ) = 0;\r
+    virtual HRESULT __stdcall get_Precision (\r
+        unsigned char * pbPrecision ) = 0;\r
+    virtual HRESULT __stdcall get_NumericScale (\r
+        unsigned char * pbNumericScale ) = 0;\r
+    virtual HRESULT __stdcall raw_AppendChunk (\r
+        VARIANT Data ) = 0;\r
+    virtual HRESULT __stdcall raw_GetChunk (\r
+        long Length,\r
+        VARIANT * pvar ) = 0;\r
+    virtual HRESULT __stdcall get_OriginalValue (\r
+        VARIANT * pvar ) = 0;\r
+    virtual HRESULT __stdcall get_UnderlyingValue (\r
+        VARIANT * pvar ) = 0;\r
+};\r
+\r
+struct __declspec(uuid("0000050b-0000-0010-8000-00aa006d2ea4"))\r
+Parameter;\r
+    // [ default ] interface _Parameter\r
+\r
+//\r
+// Wrapper method implementations\r
+//\r
+\r
+#include "msado15.tli"\r
+\r
+} // namespace ADODB\r
+\r
+#pragma pack(pop)\r
diff --git a/st2gpx/src/msado15.tli b/st2gpx/src/msado15.tli
new file mode 100644 (file)
index 0000000..e72d7a8
--- /dev/null
@@ -0,0 +1,2095 @@
+// Created by Microsoft (R) C/C++ Compiler Version 12.00.8168.0 (1f62c7b3).\r
+//\r
+// msado15.tli\r
+//\r
+// Wrapper implementations for Win32 type library msado15.dll\r
+// compiler-generated file created 11/21/03 at 18:38:05 - DO NOT EDIT!\r
+\r
+#pragma once\r
+\r
+//\r
+// interface _Collection wrapper method implementations\r
+//\r
+\r
+inline long _Collection::GetCount ( ) {\r
+    long _result;\r
+    HRESULT _hr = get_Count(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline IUnknownPtr _Collection::_NewEnum ( ) {\r
+    IUnknown * _result;\r
+    HRESULT _hr = raw__NewEnum(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return IUnknownPtr(_result, false);\r
+}\r
+\r
+inline HRESULT _Collection::Refresh ( ) {\r
+    HRESULT _hr = raw_Refresh();\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+//\r
+// interface _DynaCollection wrapper method implementations\r
+//\r
+\r
+inline HRESULT _DynaCollection::Append ( IDispatch * Object ) {\r
+    HRESULT _hr = raw_Append(Object);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT _DynaCollection::Delete ( const _variant_t & Index ) {\r
+    HRESULT _hr = raw_Delete(Index);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+//\r
+// interface _ADO wrapper method implementations\r
+//\r
+\r
+inline PropertiesPtr _ADO::GetProperties ( ) {\r
+    struct Properties * _result;\r
+    HRESULT _hr = get_Properties(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return PropertiesPtr(_result, false);\r
+}\r
+\r
+//\r
+// interface Properties wrapper method implementations\r
+//\r
+\r
+inline PropertyPtr Properties::GetItem ( const _variant_t & Index ) {\r
+    struct Property * _result;\r
+    HRESULT _hr = get_Item(Index, &_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return PropertyPtr(_result, false);\r
+}\r
+\r
+//\r
+// interface Property wrapper method implementations\r
+//\r
+\r
+inline _variant_t Property::GetValue ( ) {\r
+    VARIANT _result;\r
+    VariantInit(&_result);\r
+    HRESULT _hr = get_Value(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _variant_t(_result, false);\r
+}\r
+\r
+inline void Property::PutValue ( const _variant_t & pval ) {\r
+    HRESULT _hr = put_Value(pval);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline _bstr_t Property::GetName ( ) {\r
+    BSTR _result;\r
+    HRESULT _hr = get_Name(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _bstr_t(_result, false);\r
+}\r
+\r
+inline enum DataTypeEnum Property::GetType ( ) {\r
+    enum DataTypeEnum _result;\r
+    HRESULT _hr = get_Type(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline long Property::GetAttributes ( ) {\r
+    long _result;\r
+    HRESULT _hr = get_Attributes(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline void Property::PutAttributes ( long plAttributes ) {\r
+    HRESULT _hr = put_Attributes(plAttributes);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+//\r
+// interface Error wrapper method implementations\r
+//\r
+\r
+inline long Error::GetNumber ( ) {\r
+    long _result;\r
+    HRESULT _hr = get_Number(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline _bstr_t Error::GetSource ( ) {\r
+    BSTR _result;\r
+    HRESULT _hr = get_Source(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _bstr_t(_result, false);\r
+}\r
+\r
+inline _bstr_t Error::GetDescription ( ) {\r
+    BSTR _result;\r
+    HRESULT _hr = get_Description(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _bstr_t(_result, false);\r
+}\r
+\r
+inline _bstr_t Error::GetHelpFile ( ) {\r
+    BSTR _result;\r
+    HRESULT _hr = get_HelpFile(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _bstr_t(_result, false);\r
+}\r
+\r
+inline long Error::GetHelpContext ( ) {\r
+    long _result;\r
+    HRESULT _hr = get_HelpContext(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline _bstr_t Error::GetSQLState ( ) {\r
+    BSTR _result;\r
+    HRESULT _hr = get_SQLState(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _bstr_t(_result, false);\r
+}\r
+\r
+inline long Error::GetNativeError ( ) {\r
+    long _result;\r
+    HRESULT _hr = get_NativeError(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+//\r
+// interface Errors wrapper method implementations\r
+//\r
+\r
+inline ErrorPtr Errors::GetItem ( const _variant_t & Index ) {\r
+    struct Error * _result;\r
+    HRESULT _hr = get_Item(Index, &_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return ErrorPtr(_result, false);\r
+}\r
+\r
+inline HRESULT Errors::Clear ( ) {\r
+    HRESULT _hr = raw_Clear();\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+//\r
+// interface Command15 wrapper method implementations\r
+//\r
+\r
+inline _ConnectionPtr Command15::GetActiveConnection ( ) {\r
+    struct _Connection * _result;\r
+    HRESULT _hr = get_ActiveConnection(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _ConnectionPtr(_result, false);\r
+}\r
+\r
+inline void Command15::PutRefActiveConnection ( struct _Connection * ppvObject ) {\r
+    HRESULT _hr = putref_ActiveConnection(ppvObject);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline void Command15::PutActiveConnection ( const _variant_t & ppvObject ) {\r
+    HRESULT _hr = put_ActiveConnection(ppvObject);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline _bstr_t Command15::GetCommandText ( ) {\r
+    BSTR _result;\r
+    HRESULT _hr = get_CommandText(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _bstr_t(_result, false);\r
+}\r
+\r
+inline void Command15::PutCommandText ( _bstr_t pbstr ) {\r
+    HRESULT _hr = put_CommandText(pbstr);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline long Command15::GetCommandTimeout ( ) {\r
+    long _result;\r
+    HRESULT _hr = get_CommandTimeout(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline void Command15::PutCommandTimeout ( long pl ) {\r
+    HRESULT _hr = put_CommandTimeout(pl);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline VARIANT_BOOL Command15::GetPrepared ( ) {\r
+    VARIANT_BOOL _result;\r
+    HRESULT _hr = get_Prepared(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline void Command15::PutPrepared ( VARIANT_BOOL pfPrepared ) {\r
+    HRESULT _hr = put_Prepared(pfPrepared);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline _RecordsetPtr Command15::Execute ( VARIANT * RecordsAffected, VARIANT * Parameters, long Options ) {\r
+    struct _Recordset * _result;\r
+    HRESULT _hr = raw_Execute(RecordsAffected, Parameters, Options, &_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _RecordsetPtr(_result, false);\r
+}\r
+\r
+inline _ParameterPtr Command15::CreateParameter ( _bstr_t Name, enum DataTypeEnum Type, enum ParameterDirectionEnum Direction, long Size, const _variant_t & Value ) {\r
+    struct _Parameter * _result;\r
+    HRESULT _hr = raw_CreateParameter(Name, Type, Direction, Size, Value, &_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _ParameterPtr(_result, false);\r
+}\r
+\r
+inline ParametersPtr Command15::GetParameters ( ) {\r
+    struct Parameters * _result;\r
+    HRESULT _hr = get_Parameters(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return ParametersPtr(_result, false);\r
+}\r
+\r
+inline void Command15::PutCommandType ( enum CommandTypeEnum plCmdType ) {\r
+    HRESULT _hr = put_CommandType(plCmdType);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline enum CommandTypeEnum Command15::GetCommandType ( ) {\r
+    enum CommandTypeEnum _result;\r
+    HRESULT _hr = get_CommandType(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline _bstr_t Command15::GetName ( ) {\r
+    BSTR _result;\r
+    HRESULT _hr = get_Name(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _bstr_t(_result, false);\r
+}\r
+\r
+inline void Command15::PutName ( _bstr_t pbstrName ) {\r
+    HRESULT _hr = put_Name(pbstrName);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+//\r
+// interface Connection15 wrapper method implementations\r
+//\r
+\r
+inline _bstr_t Connection15::GetConnectionString ( ) {\r
+    BSTR _result;\r
+    HRESULT _hr = get_ConnectionString(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _bstr_t(_result, false);\r
+}\r
+\r
+inline void Connection15::PutConnectionString ( _bstr_t pbstr ) {\r
+    HRESULT _hr = put_ConnectionString(pbstr);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline long Connection15::GetCommandTimeout ( ) {\r
+    long _result;\r
+    HRESULT _hr = get_CommandTimeout(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline void Connection15::PutCommandTimeout ( long plTimeout ) {\r
+    HRESULT _hr = put_CommandTimeout(plTimeout);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline long Connection15::GetConnectionTimeout ( ) {\r
+    long _result;\r
+    HRESULT _hr = get_ConnectionTimeout(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline void Connection15::PutConnectionTimeout ( long plTimeout ) {\r
+    HRESULT _hr = put_ConnectionTimeout(plTimeout);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline _bstr_t Connection15::GetVersion ( ) {\r
+    BSTR _result;\r
+    HRESULT _hr = get_Version(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _bstr_t(_result, false);\r
+}\r
+\r
+inline HRESULT Connection15::Close ( ) {\r
+    HRESULT _hr = raw_Close();\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline _RecordsetPtr Connection15::Execute ( _bstr_t CommandText, VARIANT * RecordsAffected, long Options ) {\r
+    struct _Recordset * _result;\r
+    HRESULT _hr = raw_Execute(CommandText, RecordsAffected, Options, &_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _RecordsetPtr(_result, false);\r
+}\r
+\r
+inline long Connection15::BeginTrans ( ) {\r
+    long _result;\r
+    HRESULT _hr = raw_BeginTrans(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline HRESULT Connection15::CommitTrans ( ) {\r
+    HRESULT _hr = raw_CommitTrans();\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT Connection15::RollbackTrans ( ) {\r
+    HRESULT _hr = raw_RollbackTrans();\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT Connection15::Open ( _bstr_t ConnectionString, _bstr_t UserID, _bstr_t Password, long Options ) {\r
+    HRESULT _hr = raw_Open(ConnectionString, UserID, Password, Options);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline ErrorsPtr Connection15::GetErrors ( ) {\r
+    struct Errors * _result;\r
+    HRESULT _hr = get_Errors(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return ErrorsPtr(_result, false);\r
+}\r
+\r
+inline _bstr_t Connection15::GetDefaultDatabase ( ) {\r
+    BSTR _result;\r
+    HRESULT _hr = get_DefaultDatabase(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _bstr_t(_result, false);\r
+}\r
+\r
+inline void Connection15::PutDefaultDatabase ( _bstr_t pbstr ) {\r
+    HRESULT _hr = put_DefaultDatabase(pbstr);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline enum IsolationLevelEnum Connection15::GetIsolationLevel ( ) {\r
+    enum IsolationLevelEnum _result;\r
+    HRESULT _hr = get_IsolationLevel(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline void Connection15::PutIsolationLevel ( enum IsolationLevelEnum Level ) {\r
+    HRESULT _hr = put_IsolationLevel(Level);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline long Connection15::GetAttributes ( ) {\r
+    long _result;\r
+    HRESULT _hr = get_Attributes(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline void Connection15::PutAttributes ( long plAttr ) {\r
+    HRESULT _hr = put_Attributes(plAttr);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline enum CursorLocationEnum Connection15::GetCursorLocation ( ) {\r
+    enum CursorLocationEnum _result;\r
+    HRESULT _hr = get_CursorLocation(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline void Connection15::PutCursorLocation ( enum CursorLocationEnum plCursorLoc ) {\r
+    HRESULT _hr = put_CursorLocation(plCursorLoc);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline enum ConnectModeEnum Connection15::GetMode ( ) {\r
+    enum ConnectModeEnum _result;\r
+    HRESULT _hr = get_Mode(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline void Connection15::PutMode ( enum ConnectModeEnum plMode ) {\r
+    HRESULT _hr = put_Mode(plMode);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline _bstr_t Connection15::GetProvider ( ) {\r
+    BSTR _result;\r
+    HRESULT _hr = get_Provider(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _bstr_t(_result, false);\r
+}\r
+\r
+inline void Connection15::PutProvider ( _bstr_t pbstr ) {\r
+    HRESULT _hr = put_Provider(pbstr);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline long Connection15::GetState ( ) {\r
+    long _result;\r
+    HRESULT _hr = get_State(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline _RecordsetPtr Connection15::OpenSchema ( enum SchemaEnum Schema, const _variant_t & Restrictions, const _variant_t & SchemaID ) {\r
+    struct _Recordset * _result;\r
+    HRESULT _hr = raw_OpenSchema(Schema, Restrictions, SchemaID, &_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _RecordsetPtr(_result, false);\r
+}\r
+\r
+//\r
+// interface _Connection wrapper method implementations\r
+//\r
+\r
+inline HRESULT _Connection::Cancel ( ) {\r
+    HRESULT _hr = raw_Cancel();\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+//\r
+// interface Recordset15 wrapper method implementations\r
+//\r
+\r
+inline enum PositionEnum Recordset15::GetAbsolutePosition ( ) {\r
+    enum PositionEnum _result;\r
+    HRESULT _hr = get_AbsolutePosition(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline void Recordset15::PutAbsolutePosition ( enum PositionEnum pl ) {\r
+    HRESULT _hr = put_AbsolutePosition(pl);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline void Recordset15::PutRefActiveConnection ( IDispatch * pvar ) {\r
+    HRESULT _hr = putref_ActiveConnection(pvar);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline void Recordset15::PutActiveConnection ( const _variant_t & pvar ) {\r
+    HRESULT _hr = put_ActiveConnection(pvar);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline _variant_t Recordset15::GetActiveConnection ( ) {\r
+    VARIANT _result;\r
+    VariantInit(&_result);\r
+    HRESULT _hr = get_ActiveConnection(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _variant_t(_result, false);\r
+}\r
+\r
+inline VARIANT_BOOL Recordset15::GetBOF ( ) {\r
+    VARIANT_BOOL _result;\r
+    HRESULT _hr = get_BOF(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline _variant_t Recordset15::GetBookmark ( ) {\r
+    VARIANT _result;\r
+    VariantInit(&_result);\r
+    HRESULT _hr = get_Bookmark(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _variant_t(_result, false);\r
+}\r
+\r
+inline void Recordset15::PutBookmark ( const _variant_t & pvBookmark ) {\r
+    HRESULT _hr = put_Bookmark(pvBookmark);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline long Recordset15::GetCacheSize ( ) {\r
+    long _result;\r
+    HRESULT _hr = get_CacheSize(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline void Recordset15::PutCacheSize ( long pl ) {\r
+    HRESULT _hr = put_CacheSize(pl);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline enum CursorTypeEnum Recordset15::GetCursorType ( ) {\r
+    enum CursorTypeEnum _result;\r
+    HRESULT _hr = get_CursorType(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline void Recordset15::PutCursorType ( enum CursorTypeEnum plCursorType ) {\r
+    HRESULT _hr = put_CursorType(plCursorType);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline VARIANT_BOOL Recordset15::GetadoEOF ( ) {\r
+    VARIANT_BOOL _result;\r
+    HRESULT _hr = get_adoEOF(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline FieldsPtr Recordset15::GetFields ( ) {\r
+    struct Fields * _result;\r
+    HRESULT _hr = get_Fields(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return FieldsPtr(_result, false);\r
+}\r
+\r
+inline enum LockTypeEnum Recordset15::GetLockType ( ) {\r
+    enum LockTypeEnum _result;\r
+    HRESULT _hr = get_LockType(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline void Recordset15::PutLockType ( enum LockTypeEnum plLockType ) {\r
+    HRESULT _hr = put_LockType(plLockType);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline long Recordset15::GetMaxRecords ( ) {\r
+    long _result;\r
+    HRESULT _hr = get_MaxRecords(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline void Recordset15::PutMaxRecords ( long plMaxRecords ) {\r
+    HRESULT _hr = put_MaxRecords(plMaxRecords);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline long Recordset15::GetRecordCount ( ) {\r
+    long _result;\r
+    HRESULT _hr = get_RecordCount(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline void Recordset15::PutRefSource ( IDispatch * pvSource ) {\r
+    HRESULT _hr = putref_Source(pvSource);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline void Recordset15::PutSource ( _bstr_t pvSource ) {\r
+    HRESULT _hr = put_Source(pvSource);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline _variant_t Recordset15::GetSource ( ) {\r
+    VARIANT _result;\r
+    VariantInit(&_result);\r
+    HRESULT _hr = get_Source(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _variant_t(_result, false);\r
+}\r
+\r
+inline HRESULT Recordset15::AddNew ( const _variant_t & FieldList, const _variant_t & Values ) {\r
+    HRESULT _hr = raw_AddNew(FieldList, Values);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT Recordset15::CancelUpdate ( ) {\r
+    HRESULT _hr = raw_CancelUpdate();\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT Recordset15::Close ( ) {\r
+    HRESULT _hr = raw_Close();\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT Recordset15::Delete ( enum AffectEnum AffectRecords ) {\r
+    HRESULT _hr = raw_Delete(AffectRecords);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline _variant_t Recordset15::GetRows ( long Rows, const _variant_t & Start, const _variant_t & Fields ) {\r
+    VARIANT _result;\r
+    VariantInit(&_result);\r
+    HRESULT _hr = raw_GetRows(Rows, Start, Fields, &_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _variant_t(_result, false);\r
+}\r
+\r
+inline HRESULT Recordset15::Move ( long NumRecords, const _variant_t & Start ) {\r
+    HRESULT _hr = raw_Move(NumRecords, Start);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT Recordset15::MoveNext ( ) {\r
+    HRESULT _hr = raw_MoveNext();\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT Recordset15::MovePrevious ( ) {\r
+    HRESULT _hr = raw_MovePrevious();\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT Recordset15::MoveFirst ( ) {\r
+    HRESULT _hr = raw_MoveFirst();\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT Recordset15::MoveLast ( ) {\r
+    HRESULT _hr = raw_MoveLast();\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT Recordset15::Open ( const _variant_t & Source, const _variant_t & ActiveConnection, enum CursorTypeEnum CursorType, enum LockTypeEnum LockType, long Options ) {\r
+    HRESULT _hr = raw_Open(Source, ActiveConnection, CursorType, LockType, Options);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT Recordset15::Requery ( long Options ) {\r
+    HRESULT _hr = raw_Requery(Options);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT Recordset15::_xResync ( enum AffectEnum AffectRecords ) {\r
+    HRESULT _hr = raw__xResync(AffectRecords);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT Recordset15::Update ( const _variant_t & Fields, const _variant_t & Values ) {\r
+    HRESULT _hr = raw_Update(Fields, Values);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline enum PositionEnum Recordset15::GetAbsolutePage ( ) {\r
+    enum PositionEnum _result;\r
+    HRESULT _hr = get_AbsolutePage(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline void Recordset15::PutAbsolutePage ( enum PositionEnum pl ) {\r
+    HRESULT _hr = put_AbsolutePage(pl);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline enum EditModeEnum Recordset15::GetEditMode ( ) {\r
+    enum EditModeEnum _result;\r
+    HRESULT _hr = get_EditMode(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline _variant_t Recordset15::GetFilter ( ) {\r
+    VARIANT _result;\r
+    VariantInit(&_result);\r
+    HRESULT _hr = get_Filter(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _variant_t(_result, false);\r
+}\r
+\r
+inline void Recordset15::PutFilter ( const _variant_t & Criteria ) {\r
+    HRESULT _hr = put_Filter(Criteria);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline long Recordset15::GetPageCount ( ) {\r
+    long _result;\r
+    HRESULT _hr = get_PageCount(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline long Recordset15::GetPageSize ( ) {\r
+    long _result;\r
+    HRESULT _hr = get_PageSize(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline void Recordset15::PutPageSize ( long pl ) {\r
+    HRESULT _hr = put_PageSize(pl);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline _bstr_t Recordset15::GetSort ( ) {\r
+    BSTR _result;\r
+    HRESULT _hr = get_Sort(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _bstr_t(_result, false);\r
+}\r
+\r
+inline void Recordset15::PutSort ( _bstr_t Criteria ) {\r
+    HRESULT _hr = put_Sort(Criteria);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline long Recordset15::GetStatus ( ) {\r
+    long _result;\r
+    HRESULT _hr = get_Status(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline long Recordset15::GetState ( ) {\r
+    long _result;\r
+    HRESULT _hr = get_State(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline _RecordsetPtr Recordset15::_xClone ( ) {\r
+    struct _Recordset * _result;\r
+    HRESULT _hr = raw__xClone(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _RecordsetPtr(_result, false);\r
+}\r
+\r
+inline HRESULT Recordset15::UpdateBatch ( enum AffectEnum AffectRecords ) {\r
+    HRESULT _hr = raw_UpdateBatch(AffectRecords);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT Recordset15::CancelBatch ( enum AffectEnum AffectRecords ) {\r
+    HRESULT _hr = raw_CancelBatch(AffectRecords);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline enum CursorLocationEnum Recordset15::GetCursorLocation ( ) {\r
+    enum CursorLocationEnum _result;\r
+    HRESULT _hr = get_CursorLocation(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline void Recordset15::PutCursorLocation ( enum CursorLocationEnum plCursorLoc ) {\r
+    HRESULT _hr = put_CursorLocation(plCursorLoc);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline _RecordsetPtr Recordset15::NextRecordset ( VARIANT * RecordsAffected ) {\r
+    struct _Recordset * _result;\r
+    HRESULT _hr = raw_NextRecordset(RecordsAffected, &_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _RecordsetPtr(_result, false);\r
+}\r
+\r
+inline VARIANT_BOOL Recordset15::Supports ( enum CursorOptionEnum CursorOptions ) {\r
+    VARIANT_BOOL _result;\r
+    HRESULT _hr = raw_Supports(CursorOptions, &_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline _variant_t Recordset15::GetCollect ( const _variant_t & Index ) {\r
+    VARIANT _result;\r
+    VariantInit(&_result);\r
+    HRESULT _hr = get_Collect(Index, &_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _variant_t(_result, false);\r
+}\r
+\r
+inline void Recordset15::PutCollect ( const _variant_t & Index, const _variant_t & pvar ) {\r
+    HRESULT _hr = put_Collect(Index, pvar);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline enum MarshalOptionsEnum Recordset15::GetMarshalOptions ( ) {\r
+    enum MarshalOptionsEnum _result;\r
+    HRESULT _hr = get_MarshalOptions(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline void Recordset15::PutMarshalOptions ( enum MarshalOptionsEnum peMarshal ) {\r
+    HRESULT _hr = put_MarshalOptions(peMarshal);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline HRESULT Recordset15::Find ( _bstr_t Criteria, long SkipRecords, enum SearchDirectionEnum SearchDirection, const _variant_t & Start ) {\r
+    HRESULT _hr = raw_Find(Criteria, SkipRecords, SearchDirection, Start);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+//\r
+// interface Recordset20 wrapper method implementations\r
+//\r
+\r
+inline HRESULT Recordset20::Cancel ( ) {\r
+    HRESULT _hr = raw_Cancel();\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline IUnknownPtr Recordset20::GetDataSource ( ) {\r
+    IUnknown * _result;\r
+    HRESULT _hr = get_DataSource(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return IUnknownPtr(_result, false);\r
+}\r
+\r
+inline void Recordset20::PutRefDataSource ( IUnknown * ppunkDataSource ) {\r
+    HRESULT _hr = putref_DataSource(ppunkDataSource);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline HRESULT Recordset20::_xSave ( _bstr_t FileName, enum PersistFormatEnum PersistFormat ) {\r
+    HRESULT _hr = raw__xSave(FileName, PersistFormat);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline IDispatchPtr Recordset20::GetActiveCommand ( ) {\r
+    IDispatch * _result;\r
+    HRESULT _hr = get_ActiveCommand(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return IDispatchPtr(_result, false);\r
+}\r
+\r
+inline void Recordset20::PutStayInSync ( VARIANT_BOOL pbStayInSync ) {\r
+    HRESULT _hr = put_StayInSync(pbStayInSync);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline VARIANT_BOOL Recordset20::GetStayInSync ( ) {\r
+    VARIANT_BOOL _result;\r
+    HRESULT _hr = get_StayInSync(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline _bstr_t Recordset20::GetString ( enum StringFormatEnum StringFormat, long NumRows, _bstr_t ColumnDelimeter, _bstr_t RowDelimeter, _bstr_t NullExpr ) {\r
+    BSTR _result;\r
+    HRESULT _hr = raw_GetString(StringFormat, NumRows, ColumnDelimeter, RowDelimeter, NullExpr, &_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _bstr_t(_result, false);\r
+}\r
+\r
+inline _bstr_t Recordset20::GetDataMember ( ) {\r
+    BSTR _result;\r
+    HRESULT _hr = get_DataMember(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _bstr_t(_result, false);\r
+}\r
+\r
+inline void Recordset20::PutDataMember ( _bstr_t pbstrDataMember ) {\r
+    HRESULT _hr = put_DataMember(pbstrDataMember);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline enum CompareEnum Recordset20::CompareBookmarks ( const _variant_t & Bookmark1, const _variant_t & Bookmark2 ) {\r
+    enum CompareEnum _result;\r
+    HRESULT _hr = raw_CompareBookmarks(Bookmark1, Bookmark2, &_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline _RecordsetPtr Recordset20::Clone ( enum LockTypeEnum LockType ) {\r
+    struct _Recordset * _result;\r
+    HRESULT _hr = raw_Clone(LockType, &_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _RecordsetPtr(_result, false);\r
+}\r
+\r
+inline HRESULT Recordset20::Resync ( enum AffectEnum AffectRecords, enum ResyncEnum ResyncValues ) {\r
+    HRESULT _hr = raw_Resync(AffectRecords, ResyncValues);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+//\r
+// interface Recordset21 wrapper method implementations\r
+//\r
+\r
+inline HRESULT Recordset21::Seek ( const _variant_t & KeyValues, enum SeekEnum SeekOption ) {\r
+    HRESULT _hr = raw_Seek(KeyValues, SeekOption);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline void Recordset21::PutIndex ( _bstr_t pbstrIndex ) {\r
+    HRESULT _hr = put_Index(pbstrIndex);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline _bstr_t Recordset21::GetIndex ( ) {\r
+    BSTR _result;\r
+    HRESULT _hr = get_Index(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _bstr_t(_result, false);\r
+}\r
+\r
+//\r
+// interface _Recordset wrapper method implementations\r
+//\r
+\r
+inline HRESULT _Recordset::Save ( const _variant_t & Destination, enum PersistFormatEnum PersistFormat ) {\r
+    HRESULT _hr = raw_Save(Destination, PersistFormat);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+//\r
+// interface Fields15 wrapper method implementations\r
+//\r
+\r
+inline FieldPtr Fields15::GetItem ( const _variant_t & Index ) {\r
+    struct Field * _result;\r
+    HRESULT _hr = get_Item(Index, &_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return FieldPtr(_result, false);\r
+}\r
+\r
+//\r
+// interface Fields20 wrapper method implementations\r
+//\r
+\r
+inline HRESULT Fields20::_Append ( _bstr_t Name, enum DataTypeEnum Type, long DefinedSize, enum FieldAttributeEnum Attrib ) {\r
+    HRESULT _hr = raw__Append(Name, Type, DefinedSize, Attrib);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT Fields20::Delete ( const _variant_t & Index ) {\r
+    HRESULT _hr = raw_Delete(Index);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+//\r
+// interface Fields wrapper method implementations\r
+//\r
+\r
+inline HRESULT Fields::Append ( _bstr_t Name, enum DataTypeEnum Type, long DefinedSize, enum FieldAttributeEnum Attrib, const _variant_t & FieldValue ) {\r
+    HRESULT _hr = raw_Append(Name, Type, DefinedSize, Attrib, FieldValue);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT Fields::Update ( ) {\r
+    HRESULT _hr = raw_Update();\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT Fields::Resync ( enum ResyncEnum ResyncValues ) {\r
+    HRESULT _hr = raw_Resync(ResyncValues);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT Fields::CancelUpdate ( ) {\r
+    HRESULT _hr = raw_CancelUpdate();\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+//\r
+// interface Field20 wrapper method implementations\r
+//\r
+\r
+inline long Field20::GetActualSize ( ) {\r
+    long _result;\r
+    HRESULT _hr = get_ActualSize(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline long Field20::GetAttributes ( ) {\r
+    long _result;\r
+    HRESULT _hr = get_Attributes(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline long Field20::GetDefinedSize ( ) {\r
+    long _result;\r
+    HRESULT _hr = get_DefinedSize(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline _bstr_t Field20::GetName ( ) {\r
+    BSTR _result;\r
+    HRESULT _hr = get_Name(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _bstr_t(_result, false);\r
+}\r
+\r
+inline enum DataTypeEnum Field20::GetType ( ) {\r
+    enum DataTypeEnum _result;\r
+    HRESULT _hr = get_Type(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline _variant_t Field20::GetValue ( ) {\r
+    VARIANT _result;\r
+    VariantInit(&_result);\r
+    HRESULT _hr = get_Value(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _variant_t(_result, false);\r
+}\r
+\r
+inline void Field20::PutValue ( const _variant_t & pvar ) {\r
+    HRESULT _hr = put_Value(pvar);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline unsigned char Field20::GetPrecision ( ) {\r
+    unsigned char _result;\r
+    HRESULT _hr = get_Precision(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline unsigned char Field20::GetNumericScale ( ) {\r
+    unsigned char _result;\r
+    HRESULT _hr = get_NumericScale(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline HRESULT Field20::AppendChunk ( const _variant_t & Data ) {\r
+    HRESULT _hr = raw_AppendChunk(Data);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline _variant_t Field20::GetChunk ( long Length ) {\r
+    VARIANT _result;\r
+    VariantInit(&_result);\r
+    HRESULT _hr = raw_GetChunk(Length, &_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _variant_t(_result, false);\r
+}\r
+\r
+inline _variant_t Field20::GetOriginalValue ( ) {\r
+    VARIANT _result;\r
+    VariantInit(&_result);\r
+    HRESULT _hr = get_OriginalValue(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _variant_t(_result, false);\r
+}\r
+\r
+inline _variant_t Field20::GetUnderlyingValue ( ) {\r
+    VARIANT _result;\r
+    VariantInit(&_result);\r
+    HRESULT _hr = get_UnderlyingValue(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _variant_t(_result, false);\r
+}\r
+\r
+inline IUnknownPtr Field20::GetDataFormat ( ) {\r
+    IUnknown * _result;\r
+    HRESULT _hr = get_DataFormat(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return IUnknownPtr(_result, false);\r
+}\r
+\r
+inline void Field20::PutRefDataFormat ( IUnknown * ppiDF ) {\r
+    HRESULT _hr = putref_DataFormat(ppiDF);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline void Field20::PutPrecision ( unsigned char pbPrecision ) {\r
+    HRESULT _hr = put_Precision(pbPrecision);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline void Field20::PutNumericScale ( unsigned char pbNumericScale ) {\r
+    HRESULT _hr = put_NumericScale(pbNumericScale);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline void Field20::PutType ( enum DataTypeEnum pDataType ) {\r
+    HRESULT _hr = put_Type(pDataType);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline void Field20::PutDefinedSize ( long pl ) {\r
+    HRESULT _hr = put_DefinedSize(pl);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline void Field20::PutAttributes ( long pl ) {\r
+    HRESULT _hr = put_Attributes(pl);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+//\r
+// interface Field wrapper method implementations\r
+//\r
+\r
+inline long Field::GetStatus ( ) {\r
+    long _result;\r
+    HRESULT _hr = get_Status(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+//\r
+// interface _Parameter wrapper method implementations\r
+//\r
+\r
+inline _bstr_t _Parameter::GetName ( ) {\r
+    BSTR _result;\r
+    HRESULT _hr = get_Name(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _bstr_t(_result, false);\r
+}\r
+\r
+inline void _Parameter::PutName ( _bstr_t pbstr ) {\r
+    HRESULT _hr = put_Name(pbstr);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline _variant_t _Parameter::GetValue ( ) {\r
+    VARIANT _result;\r
+    VariantInit(&_result);\r
+    HRESULT _hr = get_Value(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _variant_t(_result, false);\r
+}\r
+\r
+inline void _Parameter::PutValue ( const _variant_t & pvar ) {\r
+    HRESULT _hr = put_Value(pvar);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline enum DataTypeEnum _Parameter::GetType ( ) {\r
+    enum DataTypeEnum _result;\r
+    HRESULT _hr = get_Type(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline void _Parameter::PutType ( enum DataTypeEnum psDataType ) {\r
+    HRESULT _hr = put_Type(psDataType);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline void _Parameter::PutDirection ( enum ParameterDirectionEnum plParmDirection ) {\r
+    HRESULT _hr = put_Direction(plParmDirection);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline enum ParameterDirectionEnum _Parameter::GetDirection ( ) {\r
+    enum ParameterDirectionEnum _result;\r
+    HRESULT _hr = get_Direction(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline void _Parameter::PutPrecision ( unsigned char pbPrecision ) {\r
+    HRESULT _hr = put_Precision(pbPrecision);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline unsigned char _Parameter::GetPrecision ( ) {\r
+    unsigned char _result;\r
+    HRESULT _hr = get_Precision(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline void _Parameter::PutNumericScale ( unsigned char pbScale ) {\r
+    HRESULT _hr = put_NumericScale(pbScale);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline unsigned char _Parameter::GetNumericScale ( ) {\r
+    unsigned char _result;\r
+    HRESULT _hr = get_NumericScale(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline void _Parameter::PutSize ( long pl ) {\r
+    HRESULT _hr = put_Size(pl);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline long _Parameter::GetSize ( ) {\r
+    long _result;\r
+    HRESULT _hr = get_Size(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline HRESULT _Parameter::AppendChunk ( const _variant_t & Val ) {\r
+    HRESULT _hr = raw_AppendChunk(Val);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline long _Parameter::GetAttributes ( ) {\r
+    long _result;\r
+    HRESULT _hr = get_Attributes(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline void _Parameter::PutAttributes ( long plParmAttribs ) {\r
+    HRESULT _hr = put_Attributes(plParmAttribs);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+//\r
+// interface Parameters wrapper method implementations\r
+//\r
+\r
+inline _ParameterPtr Parameters::GetItem ( const _variant_t & Index ) {\r
+    struct _Parameter * _result;\r
+    HRESULT _hr = get_Item(Index, &_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _ParameterPtr(_result, false);\r
+}\r
+\r
+//\r
+// interface _Command wrapper method implementations\r
+//\r
+\r
+inline long _Command::GetState ( ) {\r
+    long _result;\r
+    HRESULT _hr = get_State(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline HRESULT _Command::Cancel ( ) {\r
+    HRESULT _hr = raw_Cancel();\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+//\r
+// interface ConnectionEventsVt wrapper method implementations\r
+//\r
+\r
+inline HRESULT ConnectionEventsVt::InfoMessage ( struct Error * pError, enum EventStatusEnum * adStatus, struct _Connection * pConnection ) {\r
+    HRESULT _hr = raw_InfoMessage(pError, adStatus, pConnection);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT ConnectionEventsVt::BeginTransComplete ( long TransactionLevel, struct Error * pError, enum EventStatusEnum * adStatus, struct _Connection * pConnection ) {\r
+    HRESULT _hr = raw_BeginTransComplete(TransactionLevel, pError, adStatus, pConnection);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT ConnectionEventsVt::CommitTransComplete ( struct Error * pError, enum EventStatusEnum * adStatus, struct _Connection * pConnection ) {\r
+    HRESULT _hr = raw_CommitTransComplete(pError, adStatus, pConnection);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT ConnectionEventsVt::RollbackTransComplete ( struct Error * pError, enum EventStatusEnum * adStatus, struct _Connection * pConnection ) {\r
+    HRESULT _hr = raw_RollbackTransComplete(pError, adStatus, pConnection);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT ConnectionEventsVt::WillExecute ( BSTR * Source, enum CursorTypeEnum * CursorType, enum LockTypeEnum * LockType, long * Options, enum EventStatusEnum * adStatus, struct _Command * pCommand, struct _Recordset * pRecordset, struct _Connection * pConnection ) {\r
+    HRESULT _hr = raw_WillExecute(Source, CursorType, LockType, Options, adStatus, pCommand, pRecordset, pConnection);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT ConnectionEventsVt::ExecuteComplete ( long RecordsAffected, struct Error * pError, enum EventStatusEnum * adStatus, struct _Command * pCommand, struct _Recordset * pRecordset, struct _Connection * pConnection ) {\r
+    HRESULT _hr = raw_ExecuteComplete(RecordsAffected, pError, adStatus, pCommand, pRecordset, pConnection);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT ConnectionEventsVt::WillConnect ( BSTR * ConnectionString, BSTR * UserID, BSTR * Password, long * Options, enum EventStatusEnum * adStatus, struct _Connection * pConnection ) {\r
+    HRESULT _hr = raw_WillConnect(ConnectionString, UserID, Password, Options, adStatus, pConnection);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT ConnectionEventsVt::ConnectComplete ( struct Error * pError, enum EventStatusEnum * adStatus, struct _Connection * pConnection ) {\r
+    HRESULT _hr = raw_ConnectComplete(pError, adStatus, pConnection);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT ConnectionEventsVt::Disconnect ( enum EventStatusEnum * adStatus, struct _Connection * pConnection ) {\r
+    HRESULT _hr = raw_Disconnect(adStatus, pConnection);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+//\r
+// interface RecordsetEventsVt wrapper method implementations\r
+//\r
+\r
+inline HRESULT RecordsetEventsVt::WillChangeField ( long cFields, const _variant_t & Fields, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) {\r
+    HRESULT _hr = raw_WillChangeField(cFields, Fields, adStatus, pRecordset);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT RecordsetEventsVt::FieldChangeComplete ( long cFields, const _variant_t & Fields, struct Error * pError, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) {\r
+    HRESULT _hr = raw_FieldChangeComplete(cFields, Fields, pError, adStatus, pRecordset);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT RecordsetEventsVt::WillChangeRecord ( enum EventReasonEnum adReason, long cRecords, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) {\r
+    HRESULT _hr = raw_WillChangeRecord(adReason, cRecords, adStatus, pRecordset);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT RecordsetEventsVt::RecordChangeComplete ( enum EventReasonEnum adReason, long cRecords, struct Error * pError, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) {\r
+    HRESULT _hr = raw_RecordChangeComplete(adReason, cRecords, pError, adStatus, pRecordset);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT RecordsetEventsVt::WillChangeRecordset ( enum EventReasonEnum adReason, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) {\r
+    HRESULT _hr = raw_WillChangeRecordset(adReason, adStatus, pRecordset);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT RecordsetEventsVt::RecordsetChangeComplete ( enum EventReasonEnum adReason, struct Error * pError, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) {\r
+    HRESULT _hr = raw_RecordsetChangeComplete(adReason, pError, adStatus, pRecordset);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT RecordsetEventsVt::WillMove ( enum EventReasonEnum adReason, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) {\r
+    HRESULT _hr = raw_WillMove(adReason, adStatus, pRecordset);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT RecordsetEventsVt::MoveComplete ( enum EventReasonEnum adReason, struct Error * pError, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) {\r
+    HRESULT _hr = raw_MoveComplete(adReason, pError, adStatus, pRecordset);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT RecordsetEventsVt::EndOfRecordset ( VARIANT_BOOL * fMoreData, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) {\r
+    HRESULT _hr = raw_EndOfRecordset(fMoreData, adStatus, pRecordset);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT RecordsetEventsVt::FetchProgress ( long Progress, long MaxProgress, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) {\r
+    HRESULT _hr = raw_FetchProgress(Progress, MaxProgress, adStatus, pRecordset);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT RecordsetEventsVt::FetchComplete ( struct Error * pError, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) {\r
+    HRESULT _hr = raw_FetchComplete(pError, adStatus, pRecordset);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+//\r
+// dispinterface ConnectionEvents wrapper method implementations\r
+//\r
+\r
+inline HRESULT ConnectionEvents::InfoMessage ( struct Error * pError, enum EventStatusEnum * adStatus, struct _Connection * pConnection ) {\r
+    HRESULT _result;\r
+    _com_dispatch_method(this, 0x0, DISPATCH_METHOD, VT_ERROR, (void*)&_result, \r
+        L"\x0009\x4003\x0009", pError, adStatus, pConnection);\r
+    return _result;\r
+}\r
+\r
+inline HRESULT ConnectionEvents::BeginTransComplete ( long TransactionLevel, struct Error * pError, enum EventStatusEnum * adStatus, struct _Connection * pConnection ) {\r
+    HRESULT _result;\r
+    _com_dispatch_method(this, 0x1, DISPATCH_METHOD, VT_ERROR, (void*)&_result, \r
+        L"\x0003\x0009\x4003\x0009", TransactionLevel, pError, adStatus, pConnection);\r
+    return _result;\r
+}\r
+\r
+inline HRESULT ConnectionEvents::CommitTransComplete ( struct Error * pError, enum EventStatusEnum * adStatus, struct _Connection * pConnection ) {\r
+    HRESULT _result;\r
+    _com_dispatch_method(this, 0x3, DISPATCH_METHOD, VT_ERROR, (void*)&_result, \r
+        L"\x0009\x4003\x0009", pError, adStatus, pConnection);\r
+    return _result;\r
+}\r
+\r
+inline HRESULT ConnectionEvents::RollbackTransComplete ( struct Error * pError, enum EventStatusEnum * adStatus, struct _Connection * pConnection ) {\r
+    HRESULT _result;\r
+    _com_dispatch_method(this, 0x2, DISPATCH_METHOD, VT_ERROR, (void*)&_result, \r
+        L"\x0009\x4003\x0009", pError, adStatus, pConnection);\r
+    return _result;\r
+}\r
+\r
+inline HRESULT ConnectionEvents::WillExecute ( BSTR * Source, enum CursorTypeEnum * CursorType, enum LockTypeEnum * LockType, long * Options, enum EventStatusEnum * adStatus, struct _Command * pCommand, struct _Recordset * pRecordset, struct _Connection * pConnection ) {\r
+    HRESULT _result;\r
+    _com_dispatch_method(this, 0x4, DISPATCH_METHOD, VT_ERROR, (void*)&_result, \r
+        L"\x4008\x4003\x4003\x4003\x4003\x0009\x0009\x0009", Source, CursorType, LockType, Options, adStatus, pCommand, pRecordset, pConnection);\r
+    return _result;\r
+}\r
+\r
+inline HRESULT ConnectionEvents::ExecuteComplete ( long RecordsAffected, struct Error * pError, enum EventStatusEnum * adStatus, struct _Command * pCommand, struct _Recordset * pRecordset, struct _Connection * pConnection ) {\r
+    HRESULT _result;\r
+    _com_dispatch_method(this, 0x5, DISPATCH_METHOD, VT_ERROR, (void*)&_result, \r
+        L"\x0003\x0009\x4003\x0009\x0009\x0009", RecordsAffected, pError, adStatus, pCommand, pRecordset, pConnection);\r
+    return _result;\r
+}\r
+\r
+inline HRESULT ConnectionEvents::WillConnect ( BSTR * ConnectionString, BSTR * UserID, BSTR * Password, long * Options, enum EventStatusEnum * adStatus, struct _Connection * pConnection ) {\r
+    HRESULT _result;\r
+    _com_dispatch_method(this, 0x6, DISPATCH_METHOD, VT_ERROR, (void*)&_result, \r
+        L"\x4008\x4008\x4008\x4003\x4003\x0009", ConnectionString, UserID, Password, Options, adStatus, pConnection);\r
+    return _result;\r
+}\r
+\r
+inline HRESULT ConnectionEvents::ConnectComplete ( struct Error * pError, enum EventStatusEnum * adStatus, struct _Connection * pConnection ) {\r
+    HRESULT _result;\r
+    _com_dispatch_method(this, 0x7, DISPATCH_METHOD, VT_ERROR, (void*)&_result, \r
+        L"\x0009\x4003\x0009", pError, adStatus, pConnection);\r
+    return _result;\r
+}\r
+\r
+inline HRESULT ConnectionEvents::Disconnect ( enum EventStatusEnum * adStatus, struct _Connection * pConnection ) {\r
+    HRESULT _result;\r
+    _com_dispatch_method(this, 0x8, DISPATCH_METHOD, VT_ERROR, (void*)&_result, \r
+        L"\x4003\x0009", adStatus, pConnection);\r
+    return _result;\r
+}\r
+\r
+//\r
+// dispinterface RecordsetEvents wrapper method implementations\r
+//\r
+\r
+inline HRESULT RecordsetEvents::WillChangeField ( long cFields, const _variant_t & Fields, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) {\r
+    HRESULT _result;\r
+    _com_dispatch_method(this, 0x9, DISPATCH_METHOD, VT_ERROR, (void*)&_result, \r
+        L"\x0003\x000c\x4003\x0009", cFields, &Fields, adStatus, pRecordset);\r
+    return _result;\r
+}\r
+\r
+inline HRESULT RecordsetEvents::FieldChangeComplete ( long cFields, const _variant_t & Fields, struct Error * pError, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) {\r
+    HRESULT _result;\r
+    _com_dispatch_method(this, 0xa, DISPATCH_METHOD, VT_ERROR, (void*)&_result, \r
+        L"\x0003\x000c\x0009\x4003\x0009", cFields, &Fields, pError, adStatus, pRecordset);\r
+    return _result;\r
+}\r
+\r
+inline HRESULT RecordsetEvents::WillChangeRecord ( enum EventReasonEnum adReason, long cRecords, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) {\r
+    HRESULT _result;\r
+    _com_dispatch_method(this, 0xb, DISPATCH_METHOD, VT_ERROR, (void*)&_result, \r
+        L"\x0003\x0003\x4003\x0009", adReason, cRecords, adStatus, pRecordset);\r
+    return _result;\r
+}\r
+\r
+inline HRESULT RecordsetEvents::RecordChangeComplete ( enum EventReasonEnum adReason, long cRecords, struct Error * pError, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) {\r
+    HRESULT _result;\r
+    _com_dispatch_method(this, 0xc, DISPATCH_METHOD, VT_ERROR, (void*)&_result, \r
+        L"\x0003\x0003\x0009\x4003\x0009", adReason, cRecords, pError, adStatus, pRecordset);\r
+    return _result;\r
+}\r
+\r
+inline HRESULT RecordsetEvents::WillChangeRecordset ( enum EventReasonEnum adReason, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) {\r
+    HRESULT _result;\r
+    _com_dispatch_method(this, 0xd, DISPATCH_METHOD, VT_ERROR, (void*)&_result, \r
+        L"\x0003\x4003\x0009", adReason, adStatus, pRecordset);\r
+    return _result;\r
+}\r
+\r
+inline HRESULT RecordsetEvents::RecordsetChangeComplete ( enum EventReasonEnum adReason, struct Error * pError, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) {\r
+    HRESULT _result;\r
+    _com_dispatch_method(this, 0xe, DISPATCH_METHOD, VT_ERROR, (void*)&_result, \r
+        L"\x0003\x0009\x4003\x0009", adReason, pError, adStatus, pRecordset);\r
+    return _result;\r
+}\r
+\r
+inline HRESULT RecordsetEvents::WillMove ( enum EventReasonEnum adReason, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) {\r
+    HRESULT _result;\r
+    _com_dispatch_method(this, 0xf, DISPATCH_METHOD, VT_ERROR, (void*)&_result, \r
+        L"\x0003\x4003\x0009", adReason, adStatus, pRecordset);\r
+    return _result;\r
+}\r
+\r
+inline HRESULT RecordsetEvents::MoveComplete ( enum EventReasonEnum adReason, struct Error * pError, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) {\r
+    HRESULT _result;\r
+    _com_dispatch_method(this, 0x10, DISPATCH_METHOD, VT_ERROR, (void*)&_result, \r
+        L"\x0003\x0009\x4003\x0009", adReason, pError, adStatus, pRecordset);\r
+    return _result;\r
+}\r
+\r
+inline HRESULT RecordsetEvents::EndOfRecordset ( VARIANT_BOOL * fMoreData, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) {\r
+    HRESULT _result;\r
+    _com_dispatch_method(this, 0x11, DISPATCH_METHOD, VT_ERROR, (void*)&_result, \r
+        L"\x400b\x4003\x0009", fMoreData, adStatus, pRecordset);\r
+    return _result;\r
+}\r
+\r
+inline HRESULT RecordsetEvents::FetchProgress ( long Progress, long MaxProgress, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) {\r
+    HRESULT _result;\r
+    _com_dispatch_method(this, 0x12, DISPATCH_METHOD, VT_ERROR, (void*)&_result, \r
+        L"\x0003\x0003\x4003\x0009", Progress, MaxProgress, adStatus, pRecordset);\r
+    return _result;\r
+}\r
+\r
+inline HRESULT RecordsetEvents::FetchComplete ( struct Error * pError, enum EventStatusEnum * adStatus, struct _Recordset * pRecordset ) {\r
+    HRESULT _result;\r
+    _com_dispatch_method(this, 0x13, DISPATCH_METHOD, VT_ERROR, (void*)&_result, \r
+        L"\x0009\x4003\x0009", pError, adStatus, pRecordset);\r
+    return _result;\r
+}\r
+\r
+//\r
+// interface ADOConnectionConstruction15 wrapper method implementations\r
+//\r
+\r
+inline IUnknownPtr ADOConnectionConstruction15::GetDSO ( ) {\r
+    IUnknown * _result;\r
+    HRESULT _hr = get_DSO(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return IUnknownPtr(_result, false);\r
+}\r
+\r
+inline IUnknownPtr ADOConnectionConstruction15::GetSession ( ) {\r
+    IUnknown * _result;\r
+    HRESULT _hr = get_Session(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return IUnknownPtr(_result, false);\r
+}\r
+\r
+inline HRESULT ADOConnectionConstruction15::WrapDSOandSession ( IUnknown * pDSO, IUnknown * pSession ) {\r
+    HRESULT _hr = raw_WrapDSOandSession(pDSO, pSession);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+//\r
+// interface _Record wrapper method implementations\r
+//\r
+\r
+inline _variant_t _Record::GetActiveConnection ( ) {\r
+    VARIANT _result;\r
+    VariantInit(&_result);\r
+    HRESULT _hr = get_ActiveConnection(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _variant_t(_result, false);\r
+}\r
+\r
+inline void _Record::PutActiveConnection ( _bstr_t pvar ) {\r
+    HRESULT _hr = put_ActiveConnection(pvar);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline void _Record::PutRefActiveConnection ( struct _Connection * pvar ) {\r
+    HRESULT _hr = putref_ActiveConnection(pvar);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline enum ObjectStateEnum _Record::GetState ( ) {\r
+    enum ObjectStateEnum _result;\r
+    HRESULT _hr = get_State(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline _variant_t _Record::GetSource ( ) {\r
+    VARIANT _result;\r
+    VariantInit(&_result);\r
+    HRESULT _hr = get_Source(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _variant_t(_result, false);\r
+}\r
+\r
+inline void _Record::PutSource ( _bstr_t pvar ) {\r
+    HRESULT _hr = put_Source(pvar);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline void _Record::PutRefSource ( IDispatch * pvar ) {\r
+    HRESULT _hr = putref_Source(pvar);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline enum ConnectModeEnum _Record::GetMode ( ) {\r
+    enum ConnectModeEnum _result;\r
+    HRESULT _hr = get_Mode(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline void _Record::PutMode ( enum ConnectModeEnum pMode ) {\r
+    HRESULT _hr = put_Mode(pMode);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline _bstr_t _Record::GetParentURL ( ) {\r
+    BSTR _result;\r
+    HRESULT _hr = get_ParentURL(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _bstr_t(_result, false);\r
+}\r
+\r
+inline _bstr_t _Record::MoveRecord ( _bstr_t Source, _bstr_t Destination, _bstr_t UserName, _bstr_t Password, enum MoveRecordOptionsEnum Options, VARIANT_BOOL Async ) {\r
+    BSTR _result;\r
+    HRESULT _hr = raw_MoveRecord(Source, Destination, UserName, Password, Options, Async, &_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _bstr_t(_result, false);\r
+}\r
+\r
+inline _bstr_t _Record::CopyRecord ( _bstr_t Source, _bstr_t Destination, _bstr_t UserName, _bstr_t Password, enum CopyRecordOptionsEnum Options, VARIANT_BOOL Async ) {\r
+    BSTR _result;\r
+    HRESULT _hr = raw_CopyRecord(Source, Destination, UserName, Password, Options, Async, &_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _bstr_t(_result, false);\r
+}\r
+\r
+inline HRESULT _Record::DeleteRecord ( _bstr_t Source, VARIANT_BOOL Async ) {\r
+    HRESULT _hr = raw_DeleteRecord(Source, Async);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT _Record::Open ( const _variant_t & Source, const _variant_t & ActiveConnection, enum ConnectModeEnum Mode, enum RecordCreateOptionsEnum CreateOptions, enum RecordOpenOptionsEnum Options, _bstr_t UserName, _bstr_t Password ) {\r
+    HRESULT _hr = raw_Open(Source, ActiveConnection, Mode, CreateOptions, Options, UserName, Password);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT _Record::Close ( ) {\r
+    HRESULT _hr = raw_Close();\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline FieldsPtr _Record::GetFields ( ) {\r
+    struct Fields * _result;\r
+    HRESULT _hr = get_Fields(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return FieldsPtr(_result, false);\r
+}\r
+\r
+inline enum RecordTypeEnum _Record::GetRecordType ( ) {\r
+    enum RecordTypeEnum _result;\r
+    HRESULT _hr = get_RecordType(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline _RecordsetPtr _Record::GetChildren ( ) {\r
+    struct _Recordset * _result;\r
+    HRESULT _hr = raw_GetChildren(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _RecordsetPtr(_result, false);\r
+}\r
+\r
+inline HRESULT _Record::Cancel ( ) {\r
+    HRESULT _hr = raw_Cancel();\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+//\r
+// interface IRecFields wrapper method implementations\r
+//\r
+\r
+inline HRESULT IRecFields::ADOCheck ( ) {\r
+    HRESULT _hr = raw_ADOCheck();\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+//\r
+// interface _Stream wrapper method implementations\r
+//\r
+\r
+inline long _Stream::GetSize ( ) {\r
+    long _result;\r
+    HRESULT _hr = get_Size(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline VARIANT_BOOL _Stream::GetEOS ( ) {\r
+    VARIANT_BOOL _result;\r
+    HRESULT _hr = get_EOS(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline long _Stream::GetPosition ( ) {\r
+    long _result;\r
+    HRESULT _hr = get_Position(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline void _Stream::PutPosition ( long pPos ) {\r
+    HRESULT _hr = put_Position(pPos);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline enum StreamTypeEnum _Stream::GetType ( ) {\r
+    enum StreamTypeEnum _result;\r
+    HRESULT _hr = get_Type(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline void _Stream::PutType ( enum StreamTypeEnum ptype ) {\r
+    HRESULT _hr = put_Type(ptype);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline enum LineSeparatorEnum _Stream::GetLineSeparator ( ) {\r
+    enum LineSeparatorEnum _result;\r
+    HRESULT _hr = get_LineSeparator(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline void _Stream::PutLineSeparator ( enum LineSeparatorEnum pLS ) {\r
+    HRESULT _hr = put_LineSeparator(pLS);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline enum ObjectStateEnum _Stream::GetState ( ) {\r
+    enum ObjectStateEnum _result;\r
+    HRESULT _hr = get_State(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline enum ConnectModeEnum _Stream::GetMode ( ) {\r
+    enum ConnectModeEnum _result;\r
+    HRESULT _hr = get_Mode(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline void _Stream::PutMode ( enum ConnectModeEnum pMode ) {\r
+    HRESULT _hr = put_Mode(pMode);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline _bstr_t _Stream::GetCharset ( ) {\r
+    BSTR _result;\r
+    HRESULT _hr = get_Charset(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _bstr_t(_result, false);\r
+}\r
+\r
+inline void _Stream::PutCharset ( _bstr_t pbstrCharset ) {\r
+    HRESULT _hr = put_Charset(pbstrCharset);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline _variant_t _Stream::Read ( long NumBytes ) {\r
+    VARIANT _result;\r
+    VariantInit(&_result);\r
+    HRESULT _hr = raw_Read(NumBytes, &_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _variant_t(_result, false);\r
+}\r
+\r
+inline HRESULT _Stream::Open ( const _variant_t & Source, enum ConnectModeEnum Mode, enum StreamOpenOptionsEnum Options, _bstr_t UserName, _bstr_t Password ) {\r
+    HRESULT _hr = raw_Open(Source, Mode, Options, UserName, Password);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT _Stream::Close ( ) {\r
+    HRESULT _hr = raw_Close();\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT _Stream::SkipLine ( ) {\r
+    HRESULT _hr = raw_SkipLine();\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT _Stream::Write ( const _variant_t & Buffer ) {\r
+    HRESULT _hr = raw_Write(Buffer);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT _Stream::SetEOS ( ) {\r
+    HRESULT _hr = raw_SetEOS();\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT _Stream::CopyTo ( struct _Stream * DestStream, long CharNumber ) {\r
+    HRESULT _hr = raw_CopyTo(DestStream, CharNumber);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT _Stream::Flush ( ) {\r
+    HRESULT _hr = raw_Flush();\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT _Stream::SaveToFile ( _bstr_t FileName, enum SaveOptionsEnum Options ) {\r
+    HRESULT _hr = raw_SaveToFile(FileName, Options);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT _Stream::LoadFromFile ( _bstr_t FileName ) {\r
+    HRESULT _hr = raw_LoadFromFile(FileName);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline _bstr_t _Stream::ReadText ( long NumChars ) {\r
+    BSTR _result;\r
+    HRESULT _hr = raw_ReadText(NumChars, &_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _bstr_t(_result, false);\r
+}\r
+\r
+inline HRESULT _Stream::WriteText ( _bstr_t Data, enum StreamWriteEnum Options ) {\r
+    HRESULT _hr = raw_WriteText(Data, Options);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline HRESULT _Stream::Cancel ( ) {\r
+    HRESULT _hr = raw_Cancel();\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+//\r
+// interface ADORecordConstruction wrapper method implementations\r
+//\r
+\r
+inline IUnknownPtr ADORecordConstruction::GetRow ( ) {\r
+    IUnknown * _result;\r
+    HRESULT _hr = get_Row(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return IUnknownPtr(_result, false);\r
+}\r
+\r
+inline void ADORecordConstruction::PutRow ( IUnknown * ppRow ) {\r
+    HRESULT _hr = put_Row(ppRow);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline void ADORecordConstruction::PutParentRow ( IUnknown * _arg1 ) {\r
+    HRESULT _hr = put_ParentRow(_arg1);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+//\r
+// interface ADOStreamConstruction wrapper method implementations\r
+//\r
+\r
+inline IUnknownPtr ADOStreamConstruction::GetStream ( ) {\r
+    IUnknown * _result;\r
+    HRESULT _hr = get_Stream(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return IUnknownPtr(_result, false);\r
+}\r
+\r
+inline void ADOStreamConstruction::PutStream ( IUnknown * ppStm ) {\r
+    HRESULT _hr = put_Stream(ppStm);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+//\r
+// interface ADOCommandConstruction wrapper method implementations\r
+//\r
+\r
+inline IUnknownPtr ADOCommandConstruction::GetOLEDBCommand ( ) {\r
+    IUnknown * _result;\r
+    HRESULT _hr = get_OLEDBCommand(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return IUnknownPtr(_result, false);\r
+}\r
+\r
+inline void ADOCommandConstruction::PutOLEDBCommand ( IUnknown * ppOLEDBCommand ) {\r
+    HRESULT _hr = put_OLEDBCommand(ppOLEDBCommand);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+//\r
+// interface ADORecordsetConstruction wrapper method implementations\r
+//\r
+\r
+inline IUnknownPtr ADORecordsetConstruction::GetRowset ( ) {\r
+    IUnknown * _result;\r
+    HRESULT _hr = get_Rowset(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return IUnknownPtr(_result, false);\r
+}\r
+\r
+inline void ADORecordsetConstruction::PutRowset ( IUnknown * ppRowset ) {\r
+    HRESULT _hr = put_Rowset(ppRowset);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline long ADORecordsetConstruction::GetChapter ( ) {\r
+    long _result;\r
+    HRESULT _hr = get_Chapter(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline void ADORecordsetConstruction::PutChapter ( long plChapter ) {\r
+    HRESULT _hr = put_Chapter(plChapter);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline IUnknownPtr ADORecordsetConstruction::GetRowPosition ( ) {\r
+    IUnknown * _result;\r
+    HRESULT _hr = get_RowPosition(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return IUnknownPtr(_result, false);\r
+}\r
+\r
+inline void ADORecordsetConstruction::PutRowPosition ( IUnknown * ppRowPos ) {\r
+    HRESULT _hr = put_RowPosition(ppRowPos);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+//\r
+// interface Field15 wrapper method implementations\r
+//\r
+\r
+inline long Field15::GetActualSize ( ) {\r
+    long _result;\r
+    HRESULT _hr = get_ActualSize(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline long Field15::GetAttributes ( ) {\r
+    long _result;\r
+    HRESULT _hr = get_Attributes(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline long Field15::GetDefinedSize ( ) {\r
+    long _result;\r
+    HRESULT _hr = get_DefinedSize(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline _bstr_t Field15::GetName ( ) {\r
+    BSTR _result;\r
+    HRESULT _hr = get_Name(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _bstr_t(_result, false);\r
+}\r
+\r
+inline enum DataTypeEnum Field15::GetType ( ) {\r
+    enum DataTypeEnum _result;\r
+    HRESULT _hr = get_Type(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline _variant_t Field15::GetValue ( ) {\r
+    VARIANT _result;\r
+    VariantInit(&_result);\r
+    HRESULT _hr = get_Value(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _variant_t(_result, false);\r
+}\r
+\r
+inline void Field15::PutValue ( const _variant_t & pvar ) {\r
+    HRESULT _hr = put_Value(pvar);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+}\r
+\r
+inline unsigned char Field15::GetPrecision ( ) {\r
+    unsigned char _result;\r
+    HRESULT _hr = get_Precision(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline unsigned char Field15::GetNumericScale ( ) {\r
+    unsigned char _result;\r
+    HRESULT _hr = get_NumericScale(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _result;\r
+}\r
+\r
+inline HRESULT Field15::AppendChunk ( const _variant_t & Data ) {\r
+    HRESULT _hr = raw_AppendChunk(Data);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _hr;\r
+}\r
+\r
+inline _variant_t Field15::GetChunk ( long Length ) {\r
+    VARIANT _result;\r
+    VariantInit(&_result);\r
+    HRESULT _hr = raw_GetChunk(Length, &_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _variant_t(_result, false);\r
+}\r
+\r
+inline _variant_t Field15::GetOriginalValue ( ) {\r
+    VARIANT _result;\r
+    VariantInit(&_result);\r
+    HRESULT _hr = get_OriginalValue(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _variant_t(_result, false);\r
+}\r
+\r
+inline _variant_t Field15::GetUnderlyingValue ( ) {\r
+    VARIANT _result;\r
+    VariantInit(&_result);\r
+    HRESULT _hr = get_UnderlyingValue(&_result);\r
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\r
+    return _variant_t(_result, false);\r
+}\r
diff --git a/st2gpx/src/nannol.c b/st2gpx/src/nannol.c
new file mode 100644 (file)
index 0000000..f5f0dd9
--- /dev/null
@@ -0,0 +1,206 @@
+/*\r
+       nannol.c\r
+\r
+       Extract data from MS Streets & Trips .est and Autoroute .axe files in GPX format.\r
+\r
+    Copyright (C) 2003 James Sherring, james_sherring@yahoo.com\r
+\r
+    This program is free software; you can redistribute it and/or modify\r
+    it under the terms of the GNU General Public License as published by\r
+    the Free Software Foundation; either version 2 of the License, or\r
+    (at your option) any later version.\r
+\r
+    This program is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+\r
+    You should have received a copy of the GNU General Public License\r
+    along with this program; if not, write to the Free Software\r
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA\r
+\r
+\r
+       This app depends on istorage & istorage-make from Pabs (pabs3@zip.to)\r
+       and James Clark's Expat xml parser from http://www.libexpat.org/.\r
+\r
+*/\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <memory.h>\r
+#include <math.h>\r
+\r
+#include "gpx.h"\r
+#include "st2gpx.h"\r
+#include "annotations.h"\r
+\r
+//static int readheight = 0;\r
+\r
+struct annot_rec * gpx2annot_line_rec(struct gpxpt** ptlist, int num_pts, int annot, int version)\r
+{\r
+       int i;\r
+       float x;\r
+       float y;\r
+       float z;\r
+       double lat;\r
+       double lon;\r
+       int count_points_offset;\r
+       int line_offset;\r
+\r
+       struct annot_rec * rec = annot_rec_new();\r
+\r
+       switch (version)\r
+       {\r
+       case 3:\r
+               count_points_offset = 53;\r
+               line_offset = 57;\r
+               rec->buf = (char*)xmalloc(line_offset+12*num_pts);\r
+               // copy the standard annotation header,\r
+               // with appropriate values set\r
+               memcpy(rec->buf, std_annot_linerec_header_v3, LINE_REC_LEN_V3);\r
+               break;\r
+       case 4:\r
+               count_points_offset = 53 +4;\r
+               line_offset = 57 + 4;\r
+               rec->buf = (char*)xmalloc(line_offset+12*num_pts);\r
+               // copy the standard annotation header,\r
+               // with appropriate values set\r
+               memcpy(rec->buf, std_annot_linerec_header_v4, LINE_REC_LEN_V4);\r
+               break;\r
+       default:\r
+               // FIXME version is passed as a param, should be handled there\r
+               printf("Unrecognised record format type %d, unable to process more annotations.\n", rec->type);\r
+               return NULL;\r
+               break;\r
+       }\r
+\r
+       // set the annotation (record) number\r
+       memcpy(rec->buf+4, &annot, 4);\r
+       // set the number of points in the line\r
+       memcpy(rec->buf+count_points_offset, &num_pts, 4);\r
+\r
+       for (i=0; i<num_pts; i++)\r
+       {\r
+               lat = ptlist[i]->lat;\r
+               lon = ptlist[i]->lon;\r
+               // FIXME how do I specify calc in double but return float?\r
+               x = (float)(cos(lon*M_PI/180)*cos(lat*M_PI/180));\r
+               y = (float)(sin(lon*M_PI/180)*cos(lat*M_PI/180));\r
+               z = (float)sin(lat*M_PI/180);\r
+\r
+               // We can do the height calculations also, \r
+               // and s&t will use this in some calculations, including distance,\r
+               // but there is no way to visualise or edit height in s&t.\r
+               // The example below is for cylindrical height, not radial height.\r
+\r
+/*             if (readheight) {\r
+                       // 6378137 is earths equatorial radius in meters, 20km less at the poles\r
+                       fac=1+(height/6378137);\r
+                       x *= fac;\r
+                       y *= fac;\r
+                       z *= fac;\r
+*/\r
+               memcpy(rec->buf + line_offset + 12*i,     &x, 4);\r
+               memcpy(rec->buf + line_offset + 12*i + 4, &y, 4);\r
+               memcpy(rec->buf + line_offset + 12*i + 8, &z, 4);\r
+       }\r
+\r
+       rec->length = line_offset + 12*num_pts;\r
+       rec->annot_num = annot;\r
+       rec->line_points = num_pts;\r
+       rec->line_offset = line_offset;\r
+       rec->type = ANNOT_TYPE_LINE;\r
+       return rec;\r
+}\r
+\r
+struct annotations * merge_gpx_annot(struct annotations * annots, struct gpx_data* all_gpx)\r
+{      \r
+       int i;\r
+       int this_annot_num=0;\r
+       int tot_num_annots=0;\r
+       struct gpxrte * this_rte=NULL;\r
+       struct gpxtrk * this_trk=NULL;\r
+\r
+       if ( (all_gpx==NULL) || (all_gpx->rte_list_count + all_gpx->trk_list_count==0) )\r
+               return annots;\r
+\r
+       if (annots==NULL)\r
+               annots = annotations_new();\r
+\r
+       tot_num_annots = annots->num_annotations + all_gpx->rte_list_count \r
+                                               + all_gpx->trk_list_count;\r
+\r
+       //printf("reallocing annots, from %d annotations to %d annotations\n", tot_num_annots);\r
+\r
+       annots->annot_list = (struct annot_rec**)xrealloc(annots->annot_list, \r
+                                                                                       tot_num_annots*sizeof(struct annot_rec*));\r
+\r
+       // append the gpx routes as annotation lines\r
+       for (i=0; i < (all_gpx->rte_list_count); i++) \r
+       {\r
+               this_annot_num = annots->num_annotations  + i;\r
+               this_rte = all_gpx->rte_list[i];\r
+               annots->annot_list[this_annot_num] \r
+                       = gpx2annot_line_rec(this_rte->rtept_list, \r
+                                                                this_rte->rtept_list_count, \r
+                                                                (annots->max_annot_num)+i+1,\r
+                                                                annots->version);\r
+\r
+       }\r
+\r
+       this_rte=NULL;\r
+       annots->num_annotations += all_gpx->rte_list_count;\r
+       annots->max_annot_num   += all_gpx->rte_list_count;\r
+\r
+       // append the gpx tracks as annotation lines\r
+       for (i=0; i < all_gpx->trk_list_count; i++)\r
+       {\r
+               this_annot_num = annots->num_annotations + i;\r
+               this_trk = all_gpx->trk_list[i];\r
+               annots->annot_list[this_annot_num] \r
+                       = gpx2annot_line_rec(this_trk->trkpt_list, \r
+                                                                this_trk->trkpt_list_count, \r
+                                                                (annots->max_annot_num)+i+1,\r
+                                                                annots->version);\r
+       }\r
+       annots->num_annotations += all_gpx->trk_list_count;\r
+       annots->max_annot_num   += all_gpx->trk_list_count;\r
+\r
+       memcpy(annots->header_buf+8, &(annots->num_annotations), 4);\r
+\r
+       return annots;\r
+}\r
+\r
+void write_annotations(struct annotations * annots, char* annot_out_file_name)\r
+{      // Write annotation file header\r
+       int status;\r
+       int i;\r
+       char eostream[4]={0x00, 0x00, 0x00, 0x00};\r
+       FILE* annot_out_file;\r
+\r
+       printf("Writing new annotation stream to %s\n", annot_out_file_name);\r
+\r
+       if ((annot_out_file = fopen(annot_out_file_name, "wb")) == NULL) {\r
+           fprintf(stderr, "Cannot open %s\n", annot_out_file_name);\r
+                  fflush(stdout);\r
+                       debug_pause();\r
+           exit(1);\r
+          }\r
+\r
+       status = fwrite(annots->header_buf, ANNOT_FILE_HEAD_LEN, 1, annot_out_file);\r
+       if (status != 1)\r
+               printf("expected to write %d, actually wrote %d\n", ANNOT_FILE_HEAD_LEN, status);\r
+\r
+       for(i=0; i< annots->num_annotations; i++) \r
+       {\r
+               status = fwrite(annots->annot_list[i]->buf, annots->annot_list[i]->length, 1, annot_out_file);\r
+               if (status != 1)\r
+                       printf("expected to write %d, actually wrote %d\n", annots->annot_list[i]->length, status);\r
+       }\r
+\r
+       status = fwrite(eostream, 4, 1, annot_out_file);\r
+       if (status != 1)\r
+               printf("expected to write %d, actually wrote %d\n", 4, status);\r
+\r
+    fclose(annot_out_file);\r
+}\r
diff --git a/st2gpx/src/ppinutil.c b/st2gpx/src/ppinutil.c
new file mode 100644 (file)
index 0000000..df17bb6
--- /dev/null
@@ -0,0 +1,290 @@
+/*\r
+       ppinutil.c\r
+\r
+       Extract data from MS Streets & Trips .est and Autoroute .axe files in GPX format.\r
+\r
+    Copyright (C) 2003 James Sherring, james_sherring@yahoo.com\r
+\r
+    This program is free software; you can redistribute it and/or modify\r
+    it under the terms of the GNU General Public License as published by\r
+    the Free Software Foundation; either version 2 of the License, or\r
+    (at your option) any later version.\r
+\r
+    This program is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+\r
+    You should have received a copy of the GNU General Public License\r
+    along with this program; if not, write to the Free Software\r
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA\r
+\r
+\r
+       This app depends on istorage & istorage-make from Pabs (pabs3@zip.to)\r
+       and James Clark's Expat xml parser from http://www.libexpat.org/.\r
+\r
+*/\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <malloc.h>\r
+#include <memory.h>\r
+#include <math.h>\r
+#include <string.h>\r
+\r
+#include "gpx.h"\r
+#include "st2gpx.h"\r
+#include "pushpins.h"\r
+\r
+#include "ppinutil.h"\r
+\r
+struct pushpin_safelist * pushpin_safelist_new()\r
+{\r
+       int i;\r
+       struct pushpin_safelist * nw = (struct pushpin_safelist*)xmalloc(sizeof(struct pushpin_safelist));\r
+       nw->pushpin_list=NULL;\r
+       nw->num_pushpins=0;\r
+       for(i=0; i<3; i++)\r
+       {\r
+               nw->UDM_Data_length[i]=0;\r
+               nw->UDM_Data[i]=NULL;\r
+       }\r
+       return nw;\r
+}\r
+\r
+void pushpin_safelist_delete(struct pushpin_safelist * ppl)\r
+{\r
+       int i;\r
+       if (ppl==NULL)\r
+               return;\r
+       \r
+       for (i=0; i<ppl->num_pushpins; i++)\r
+               pushpin_delete(ppl->pushpin_list[i]);\r
+       \r
+       xfree(ppl->pushpin_list);\r
+       \r
+       for(i=0; i<3; i++)\r
+               xfree(ppl->UDM_Data[i]);\r
+\r
+       xfree(ppl);\r
+}\r
+\r
+struct pushpin * pushpin_new()\r
+{\r
+       struct pushpin * nw = (struct pushpin*)xmalloc(sizeof(struct pushpin));\r
+       nw->garmin_ident[0]=0;\r
+       nw->Grid=0;\r
+       nw->Precision=0;\r
+       nw->lat=0;\r
+       nw->lon=0;\r
+       nw->NoteShort=NULL;\r
+       nw->UdName=NULL;\r
+       strcpy(nw->garmin_ident, "      ");\r
+       return nw;\r
+}\r
+\r
+void pushpin_delete(struct pushpin * pp)\r
+{\r
+       if(pp==NULL)\r
+               return;\r
+       xfree(pp->NoteShort);\r
+       xfree(pp->UdName);\r
+       xfree(pp);\r
+}\r
+\r
+struct point grid2latlon(long grid, long precision) \r
+//struct point ms2latlong(struct ms_point msp) \r
+{\r
+// Convert the 2 long values in UserData stream to GPS coordinates.\r
+\r
+// Grid and Precision are the high and low words obtained by interleaving the bits\r
+// of latitude and longitude. There is a scale factor, so that grid represents\r
+// latitude and longitude value parts more than ~ 1/182.0444 = 360/2^16,\r
+// and precision represents the rest of the values.\r
+\r
+// So we pull each 2n-th bit out, and shift it n places back to the nth longitudinal bit\r
+// and we pull each 2n-th+1 bit out, and shift it n+1 places to the nth latitudinal bit,\r
+\r
+       unsigned long int lat_mask=1;\r
+       unsigned long int lon_mask=2;\r
+       unsigned long int lat_val = 0;\r
+       unsigned long int lon_val = 0;\r
+       struct point p;\r
+\r
+       int i;\r
+\r
+       if (grid==0x3FFFFFFF)\r
+       {\r
+               printf("Got bad Grid value 0x3FFFFFFF converting pushpin data.\n");\r
+               p.lat=-180;\r
+               p.lon=-180;\r
+               return p;\r
+       }\r
+       for(i=0; i<16; i++) \r
+       {\r
+               lat_val += (lat_mask & grid) >> i;\r
+               lon_val += (lon_mask & grid) >> (i+1);\r
+               lat_mask <<= 2;\r
+               lon_mask <<= 2;\r
+       }\r
+\r
+\r
+       p.lat = (double) lat_val ;//  magic1;\r
+       p.lon = (double) lon_val ;//  magic1;\r
+\r
+       lat_mask=1;\r
+       lon_mask=2;\r
+       lat_val=0;\r
+       lon_val=0;\r
+\r
+       for (i=0; i<16; i++) \r
+       {\r
+               lat_val += (lat_mask & precision) >> i;\r
+               lon_val += (lon_mask & precision) >> (i+1);\r
+               lat_mask <<= 2;\r
+               lon_mask <<= 2;\r
+       }\r
+\r
+//     p.lat += (double) lat_val / (magic2);\r
+//     p.lon += (double) lon_val / (magic2);\r
+       p.lat += (double) lat_val / (double) (0x10000);\r
+       p.lon += (double) lon_val / (double) (0x10000);\r
+\r
+       p.lat *= 360/(double) (0x10000);\r
+       p.lon *= 360/(double) (0x10000);\r
+\r
+       if (p.lon > 180) p.lon -= 360;\r
+       if (p.lat > 180) p.lat -= 360;\r
+\r
+       if ( (p.lat > 90) || (p.lat < -90) ) \r
+       {\r
+               printf("Got bad lat value %f converting pushpin data, setting.\n");\r
+//             p.lat=-180;\r
+//             p.lon=-180;\r
+       }\r
+\r
+       return p;\r
+}\r
+\r
+struct grid_point latlon2grid(double lat, double lon) {\r
+\r
+       struct grid_point msp;\r
+       unsigned long mask=1;\r
+       int i;\r
+       double scaled_lat = (lat/360) * (0x10000);\r
+       double scaled_lon = (lon/360) * (0x10000);\r
+       unsigned long lat_grid_ndx = (unsigned long)floor(scaled_lat);\r
+       unsigned long lon_grid_ndx = (unsigned long)floor(scaled_lon);\r
+       unsigned long lat_prec_ndx = (unsigned long)floor((scaled_lat - lat_grid_ndx)*(0x10000));\r
+       unsigned long lon_prec_ndx = (unsigned long)floor((scaled_lon - lon_grid_ndx)*(0x10000));\r
+       msp.grid=0;\r
+       msp.precision=0;\r
+\r
+       for(i=0; i<16; i++) {\r
+               msp.grid += ((mask & lat_grid_ndx) << i);;\r
+               msp.grid += ((mask & lon_grid_ndx) << (i+1));\r
+               mask <<= 1;\r
+       }\r
+       \r
+       mask=1;\r
+       for(i=0; i<16; i++) {\r
+               msp.precision += ((mask & lat_prec_ndx) << i);\r
+               msp.precision += ((mask & lon_prec_ndx) << (i+1));\r
+               mask <<= 1;\r
+       }\r
+       return msp;\r
+}\r
+\r
+struct pushpin * ppin_by_UdId(int UdId, struct pushpin_safelist * ppplist)\r
+{\r
+       int i;\r
+\r
+       //printf("looking to match UdId %d to a pushpin\n", UdId);\r
+       //fflush(stdout);\r
+\r
+       if (UdId == 0)\r
+               return NULL;\r
+\r
+       if (ppplist==NULL)\r
+       {\r
+               printf("Looking for UdId %#x=%d in an empty pushpin list???\n", UdId, UdId);\r
+               return NULL;\r
+       }\r
+\r
+       for (i=0; i< ppplist->num_pushpins; i++)\r
+       {\r
+               //printf("Comparing to pushpin %d\n", i);\r
+               //fflush(stdout);\r
+               if(ppplist->pushpin_list[i] == NULL)\r
+                       return NULL;\r
+\r
+               //printf(" with UdId %ld ", (ppplist->pushpin_list[i])->UdId);\r
+               //fflush(stdout);\r
+               //printf(" and name %s\n", (ppplist->pushpin_list[i])->UdName);\r
+\r
+               if ((ppplist->pushpin_list[i]->UdId) == 0)\r
+                       return NULL;\r
+\r
+               if (ppplist->pushpin_list[i]->UdId == UdId)\r
+                       return ppplist->pushpin_list[i];\r
+       }\r
+       return NULL;\r
+}\r
+\r
+int check_file_empty(char* filename)\r
+// FIXME there must be a better way to do this\r
+{\r
+       int readchar;\r
+       int retval=0;\r
+       FILE* file = fopen(filename, "rb");\r
+       // also check if the file exists\r
+       if (file==NULL)\r
+               retval= 1;\r
+       else\r
+       {\r
+               readchar = fgetc(file);\r
+               if (readchar == EOF)\r
+                       retval=1;\r
+               else\r
+                       retval=0;\r
+       }\r
+       if (file)\r
+               fclose(file);\r
+       return retval;\r
+}\r
+\r
+struct pushpin_safelist * process_pushpin_file(char* ppin_in_file_name)\r
+{\r
+       int i=0;\r
+       struct point p;\r
+//     struct ms_point msp;\r
+       struct pushpin_safelist * ppplist;\r
+\r
+       // dont try and open a empty mdb file\r
+       if (check_file_empty(ppin_in_file_name))\r
+               return NULL;;\r
+       ppplist=read_pushpins(ppin_in_file_name);\r
+\r
+       // set lat & lon for all pushpins\r
+       while(ppplist->pushpin_list[i] && (i<ppplist->num_pushpins))\r
+       {\r
+//             msp.grid = ppplist->pushpin_list[i]->Grid;\r
+//             msp.precision = ppplist->pushpin_list[i]->Precision;\r
+//             p = grid2latlon(msp);\r
+               p = grid2latlon(ppplist->pushpin_list[i]->Grid, ppplist->pushpin_list[i]->Precision);\r
+\r
+               ppplist->pushpin_list[i]->lat = p.lat;\r
+               ppplist->pushpin_list[i]->lon = p.lon;\r
+\r
+       if (opts.verbose_flag > 3)\r
+                       printf("Decoded pushpin %d lat %f, lon %f, UdName %s, NoteShort %s\n",\r
+                               ppplist->pushpin_list[i]->UdId, ppplist->pushpin_list[i]->lat, ppplist->pushpin_list[i]->lon,\r
+                               ppplist->pushpin_list[i]->UdName, ppplist->pushpin_list[i]->NoteShort);\r
+\r
+               i++;\r
+       }\r
+\r
+       printf("Finished reading pushpins\n");\r
+       fflush(stdout);\r
+\r
+       return ppplist;\r
+}\r
diff --git a/st2gpx/src/ppinutil.h b/st2gpx/src/ppinutil.h
new file mode 100644 (file)
index 0000000..cade80e
--- /dev/null
@@ -0,0 +1,128 @@
+/*\r
+       ppinutil.h\r
+\r
+       Extract data from MS Streets & Trips .est and Autoroute .axe files in GPX format.\r
+\r
+    Copyright (C) 2003 James Sherring, james_sherring@yahoo.com\r
+\r
+    This program is free software; you can redistribute it and/or modify\r
+    it under the terms of the GNU General Public License as published by\r
+    the Free Software Foundation; either version 2 of the License, or\r
+    (at your option) any later version.\r
+\r
+    This program is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+\r
+    You should have received a copy of the GNU General Public License\r
+    along with this program; if not, write to the Free Software\r
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA\r
+\r
+\r
+       This app depends on istorage & istorage-make from Pabs (pabs3@zip.to)\r
+       and James Clark's Expat xml parser from http://www.libexpat.org/.\r
+\r
+*/\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+typedef struct pushpin_safelist\r
+{\r
+       struct pushpin ** pushpin_list;\r
+       int num_pushpins;\r
+       char * UDM_Data[3];\r
+       long UDM_Data_length[3];\r
+} tag_pushpin_safelist;\r
+\r
+typedef struct grid_point {\r
+       long grid;\r
+       long precision;\r
+} tag_ms_point;\r
+\r
+typedef struct point {\r
+       double lon;\r
+       double lat;\r
+} tag_point;\r
+\r
+// max size to be read from ppin memo fields\r
+#define MAX_PPIN_MEMO  1000\r
+\r
+typedef struct pushpin\r
+{\r
+       long UdId;\r
+       int SetId;\r
+       long Grid;\r
+       long Precision;\r
+//     dword RenderData;\r
+//     byte MatchId;\r
+//     long MOBBId;\r
+//     long SourceUdId;\r
+//     bool IsTerritory;\r
+//\r
+       char* UdName;   // max 128\r
+//     bool NoNameSearch;\r
+//     byte NoteTypeId;\r
+       char* NoteShort; // max 255\r
+//     char* NoteLong; // memo\r
+//     char* GeocodeShort; // max 255\r
+//     char* GeocodeLong; // memo\r
+//     byte GeocodeHierarchy; \r
+//     byte GeocodeContext; \r
+//     OLE Object EntityArray ????\r
+//\r
+// shouldn't include these 3 here because they are not part of the native pushpin definition\r
+       double lat;\r
+       double lon;\r
+       // 1 = by hand\r
+       // 2 = from file?\r
+       // 4 = not matched?\r
+       short int MatchId;\r
+       long MOBBId;\r
+       char garmin_ident[7];\r
+} tag_pushpin;\r
+\r
+\r
+// not used yet\r
+\r
+typedef struct pushpinset\r
+{\r
+       int SetId;\r
+       char* SetName; // max 128\r
+/*     byte RenderMethod;\r
+       byte GeocodeMethod;\r
+       byte CreateMethod;\r
+       byte GeometryType;\r
+       char[128] RenderData;\r
+       long UdCount;\r
+       long MatchedCount;\r
+       long SkippedCount;\r
+       long UnmatchedCount;\r
+       long CounterUpdateMask;\r
+       int ParentSetId;\r
+       bool IsRendered;\r
+       long Z_Order;\r
+       long GeocodeCtxt;\r
+       OLE Object ThemeRenderData\r
+       date/time LastGeocoded\r
+       char* DataSrcDescr; // memo\r
+       char[30] CurrencyData;\r
+*/\r
+} tag_pushpinset;\r
+\r
+struct pushpin * pushpin_new();\r
+void pushpin_delete(struct pushpin * pp);\r
+struct pushpin_safelist * pushpin_safelist_new();\r
+void pushpin_safelist_delete(struct pushpin_safelist * ppl);\r
+\r
+struct pushpin * ppin_by_UdId(int UdId, struct pushpin_safelist * ppplist);\r
+struct pushpin_safelist * process_pushpin_file(char* ppin_in_file_name);\r
+\r
+//struct point ms2latlong(struct ms_point msp);\r
+struct point grid2latlon(long grid, long precision);\r
+struct grid_point latlon2grid(double lat, double lon);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
diff --git a/st2gpx/src/properties.c b/st2gpx/src/properties.c
new file mode 100644 (file)
index 0000000..b8ef5f0
--- /dev/null
@@ -0,0 +1,452 @@
+/*\r
+       properties.c\r
+\r
+       Extract data from MS Streets & Trips .est and Autoroute .axe files in GPX format.\r
+\r
+    Copyright (C) 2003 James Sherring, james_sherring@yahoo.com\r
+\r
+    This program is free software; you can redistribute it and/or modify\r
+    it under the terms of the GNU General Public License as published by\r
+    the Free Software Foundation; either version 2 of the License, or\r
+    (at your option) any later version.\r
+\r
+    This program is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+\r
+    You should have received a copy of the GNU General Public License\r
+    along with this program; if not, write to the Free Software\r
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA\r
+\r
+\r
+       This app depends on istorage & istorage-make from Pabs (pabs3@zip.to)\r
+       and James Clark's Expat xml parser from http://www.libexpat.org/.\r
+\r
+*/\r
+\r
+// see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnolegen/html/msdn_propset.asp\r
+// http://www.dwam.net/docs/oleref/storage_9.htm\r
+\r
+\r
+#include <windows.h>\r
+#include <stdio.h>\r
+#include <time.h>\r
+\r
+#include "st2gpx.h"\r
+#include "properties.h"\r
+\r
+#define OLE_PROP_STREAM ".Olhud5yvVwudb10uAaq5ezn4Ac"\r
+\r
+// some types from MS, as published at\r
+// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnolegen/html/msdn_propset.asp\r
+\r
+typedef struct PROPERTYSETHEADER\r
+{\r
+     // Header\r
+     WORD    wByteOrder;      // Always 0xFFFE\r
+     WORD    wFormat;        // Always 0\r
+     WORD    dwOSVer;        // System version\r
+        // I needed to add this to get code to work with 1-byte structs alignment;\r
+        // It is normally effectively added by VC++ default compiler setting\r
+        WORD   alignment_fill;\r
+     CLSID   clsid;          // Application CLSID\r
+     DWORD   dwReserved;     // Should be 1\r
+} PROPERTYSETHEADER;\r
+\r
+typedef struct FORMATIDOFFSET\r
+{\r
+   FMTID     fmtid ;       // semantic name of a section\r
+   DWORD     dwOffset ;    // offset from start of whole property set \r
+                           // stream to the section\r
+} FORMATIDOFFSET;\r
+\r
+typedef struct PROPERTYIDOFFSET \r
+{\r
+    DWORD        propid;     // name of a property\r
+    DWORD        dwOffset;   // offset from the start of the section to that \r
+                             // property type/value pair\r
+} PROPERTYIDOFFSET;\r
+\r
+typedef struct tagPROPERTYSECTIONHEADER\r
+{\r
+    DWORD              cbSection ;         // Size of section\r
+    DWORD              cProperties ;      // Count of properties in section\r
+    PROPERTYIDOFFSET   rgPropIDOffset[];    // Array of property locations\r
+} PROPERTYSECTIONHEADER;\r
+\r
+typedef struct SERIALIZEDPROPERTYVALUE \r
+{\r
+    DWORD        dwType;      // type tag\r
+    BYTE        rgb[];        // the actual property value\r
+} SERIALIZEDPROPERTYVALUE;\r
+\r
+/*\r
+typedef struct tagENTRY {\r
+    DWORD    propid;  // Property ID\r
+    DWORD    cb;      // Count of bytes in the string, including the null \r
+                      // at the end.\r
+    char     sz[cb];  // Zero-terminated string. Code page as indicated \r
+                      // by property ID one.\r
+    } ENTRY;\r
+\r
+typedef struct tagDICTIONARY {\r
+    DWORD    cEntries;        // Count of entries in the list.\r
+    ENTRY    rgEntry[cEntries]; \r
+    } DICTIONARY;\r
+*/\r
+\r
+// my defs\r
+\r
+char * fmtid2str(char * str, char * fmtid)\r
+// normal fmtids are a 16B struct, I use a 16B char buf\r
+// fmtid should be 16B long\r
+// str should be 39B long (incl null)\r
+// We need to be careful here to get the byte order correct.\r
+// This seems to match MS's interpretation.\r
+{\r
+       sprintf(str, "{%8.8x-%4.4x-%4.4x-%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x}", \r
+                                       *(unsigned long*)(fmtid), \r
+                                       *(unsigned short*)(fmtid+4), \r
+                                       *(unsigned short*)(fmtid+6),\r
+                                       *(unsigned char*)(fmtid+8),\r
+                                       *(unsigned char*)(fmtid+9),\r
+                                       *(unsigned char*)(fmtid+10),\r
+                                       *(unsigned char*)(fmtid+11),\r
+                                       *(unsigned char*)(fmtid+12),\r
+                                       *(unsigned char*)(fmtid+13),\r
+                                       *(unsigned char*)(fmtid+14),\r
+                                       *(unsigned char*)(fmtid+15)     );\r
+       str[39]=0;\r
+       return str;\r
+}\r
+\r
+struct ole_property_set * ole_property_set_new(int cProps)\r
+{\r
+       struct ole_property_set * props \r
+               =(struct ole_property_set*)xmalloc(sizeof(struct ole_property_set)); \r
+       props->cProps = cProps;\r
+       props->dict=NULL; \r
+       props->pPropList = (struct ole_property*)xmalloc(cProps*sizeof(struct ole_property)); \r
+       return props;\r
+}\r
+\r
+void ole_property_set_delete(struct ole_property_set * props)\r
+{\r
+       unsigned int i;\r
+\r
+       if ( (props==NULL) || (props->pPropList == NULL) )\r
+               return;\r
+\r
+       for(i=0; i<props->cProps; i++)\r
+       {\r
+               xfree(props->pPropList[i].buf);\r
+               // FIXME who owns this memory? Cant free it if it is a pointer into another buff\r
+               //xfree(props->pPropList[i]);\r
+       }\r
+\r
+       if (props->dict != NULL)\r
+       {\r
+               xfree(props->dict->ent_propid);\r
+               xfree(props->dict->ent_sz);\r
+               xfree(props->dict);\r
+       }\r
+       xfree(props->pPropList);\r
+       xfree(props);\r
+}\r
+\r
+\r
+struct dictionary * read_dictionary(int ents, char* buf, int bufsize)\r
+{\r
+       int ent_read=0;\r
+       int bytes_read=0;\r
+       int this_ent_cb=0;\r
+       struct dictionary * dict = (struct dictionary *)xmalloc(sizeof(struct dictionary));\r
+       dict->cEntries = ents;\r
+       dict->ent_propid=(DWORD*)xmalloc(ents*sizeof(DWORD));\r
+       dict->ent_sz=(char**)xmalloc(ents*sizeof(char*));\r
+\r
+       printf("reading %d entries from dictionary\n", ents);\r
+\r
+       while(ent_read<ents)\r
+       {\r
+               if (bytes_read>bufsize)\r
+               {\r
+                       printf("read past end of buffer while reading properties dictionary\n");\r
+                       xfree(dict->ent_propid);\r
+                       xfree(dict->ent_sz);\r
+                       xfree(dict);\r
+                       return NULL;\r
+               }\r
+\r
+               dict->ent_propid[ent_read]=*(DWORD*)(buf+bytes_read);\r
+               bytes_read += 4;\r
+\r
+               //dict->ent_cb[ent_read]=\r
+               this_ent_cb = *(DWORD*)(buf+bytes_read);\r
+//             dict->ent_cb[ent_read]=(DWORD*)(buf+bytes_read);\r
+               bytes_read += 4;\r
+\r
+               if(this_ent_cb > 128)\r
+               {\r
+                       printf("reading dictionary, read entry for propid %#x with name length %d > max allowed length of 128\n",\r
+                               dict->ent_propid[ent_read], this_ent_cb);\r
+//                     xfree(dict->ent_cb);\r
+                       xfree(dict->ent_propid);\r
+                       xfree(dict->ent_sz);\r
+                       xfree(dict);\r
+                       return NULL;\r
+               }\r
+\r
+               // Dont allocate memory for dictionary strings,\r
+               dict->ent_sz[ent_read]=buf+bytes_read;\r
+\r
+               // MSDN documentation says cb is bytes, but it is wchars.\r
+               bytes_read += 2*this_ent_cb;\r
+\r
+               ent_read++;\r
+       }\r
+       return dict;\r
+}\r
+\r
+unsigned int get_dict_entry(struct dictionary* dict, DWORD propid)\r
+// Find a dictionary entry for a given propid.\r
+// This is then used to get the name for a propid, if available.\r
+{\r
+       unsigned int i;\r
+       if (dict==NULL)\r
+               return -1;\r
+\r
+       for(i=0; i<dict->cEntries; i++)\r
+               if (dict->ent_propid[i] == propid)\r
+                       return i;\r
+\r
+       return 1;\r
+}\r
+\r
+struct ole_property * get_propterty(struct ole_property_set * props, DWORD propid)\r
+{\r
+       unsigned int i;\r
+       \r
+       if (props==NULL)\r
+               return NULL;\r
+\r
+       for(i=0; i< props->cProps; i++)\r
+               if( props->pPropList[i].propid == propid)\r
+                       return props->pPropList+i;\r
+\r
+       return NULL;\r
+}\r
+\r
+void print_ole_properties(struct ole_property_set * props)\r
+{\r
+       unsigned int i;\r
+       unsigned int j;\r
+       char* name;\r
+       int dict_ent;\r
+       char fmtidstr[39];\r
+       char clsidstr[39];\r
+\r
+       if(props==NULL)\r
+               return;\r
+\r
+       fmtid2str(fmtidstr, props->fmtid);\r
+       fmtid2str(clsidstr, props->clsid);\r
+       printf("Printing OLE Property Set, with format id %s,\n", fmtidstr);\r
+       printf("clsid %s, os %#x osver %#x\n", clsidstr, props->OSKind, props->OSVer);\r
+\r
+       for (i=0; i< (props->cProps); i++)\r
+       {\r
+               name = NULL;\r
+               dict_ent = get_dict_entry(props->dict, props->pPropList[i].propid);\r
+               if (dict_ent != -1)\r
+                       name = props->dict->ent_sz[dict_ent];\r
+\r
+               wprintf(L"\nproperty %d: has name %s propid %#x, type %#x, and length %d bytes\n", \r
+                               i, name, props->pPropList[i].propid, \r
+                               props->pPropList[i].dwType, props->pPropList[i].buflen );\r
+\r
+               switch(props->pPropList[i].propid)\r
+               {\r
+               case 0:\r
+                       printf("This is the property-set dictionary, with entries:\n");\r
+                       printf("PropId    Property Name\n");\r
+                       printf("-----------------------\n");\r
+                       for (j=0; j<props->dict->cEntries; j++)\r
+                               wprintf(L"%#x   %s\n", props->dict->ent_propid[j], (props->dict->ent_sz[j]));\r
+                       break;\r
+               case 1:\r
+                       printf("This specifies codepage %d (1200=Unicode, 1252=Ansi).\n", \r
+                                       *(USHORT*)(props->pPropList[i].buf) );\r
+                       break;\r
+               case 0x80000000:\r
+                       printf("This specifies locale %d .\n", \r
+                                       *(unsigned short*)(props->pPropList[i].buf) );\r
+                       break;\r
+               default:\r
+                       switch(props->pPropList[i].dwType)\r
+                       {\r
+                       case VT_BSTR: //=8\r
+                       //  the prefix bytecount is still there \r
+                               wprintf(L"This has value '%ls'\n", props->pPropList[i].buf+4);\r
+                               break;\r
+                       case VT_UNKNOWN: //=13\r
+                               break;\r
+                       case VT_BOOL: // =11\r
+                               if (*(short*)(props->pPropList[i].buf))\r
+                                       printf("This has value 'True'\n");\r
+                               else\r
+                                       printf("This has value 'False'\n");\r
+                               break;\r
+                       case VT_I4: // = 3\r
+                               printf("This has value %d\n", *(int *)(props->pPropList[i].buf) );\r
+                               break;\r
+                       case VT_LPWSTR: //=31\r
+                               wprintf(L"This has value '%ls'\n", (props->pPropList[i].buf+4));\r
+                               break;\r
+                       case VT_FILETIME: //=31\r
+                               printf("This has value '%s'\n", ctime((const time_t *)props->pPropList[i].buf+4));\r
+                               break;\r
+                       default:\r
+                               printf("I dont understand this type yet\n");\r
+                               printbuf(props->pPropList[i].buf, props->pPropList[i].buflen);\r
+                               break;\r
+                       }\r
+               }\r
+       }\r
+}\r
+\r
+struct ole_property_set * read_ole_properties2(char* prop_file_name)\r
+{\r
+       FILE* prop_file=NULL;\r
+       PROPERTYSETHEADER * prop_header = (PROPERTYSETHEADER *)xmalloc(sizeof(PROPERTYSETHEADER));\r
+       FORMATIDOFFSET * fmt_id_os = (FORMATIDOFFSET *)xmalloc(sizeof(FORMATIDOFFSET));\r
+       PROPERTYSECTIONHEADER * psect_header = (PROPERTYSECTIONHEADER *)xmalloc(sizeof(PROPERTYSECTIONHEADER));\r
+       char* section_buff=NULL;\r
+       struct ole_property_set * property_set;\r
+\r
+       unsigned int i=0;\r
+       unsigned int j=0;\r
+       unsigned int next_start=0;\r
+       int status=0;\r
+\r
+       if ((prop_file = fopen(prop_file_name, "rb")) == NULL)\r
+       {\r
+               fprintf(stderr, "Cannot open property file %s\n", prop_file_name);\r
+               return NULL;\r
+       }\r
+\r
+       status=readbytes(prop_file, (char*)prop_header, sizeof(PROPERTYSETHEADER));\r
+       status=readbytes(prop_file, (char*)fmt_id_os, sizeof(FORMATIDOFFSET));\r
+\r
+       if ( (prop_header->wByteOrder != 0xFFFE) || (prop_header->wFormat != 0) \r
+                || (prop_header->dwReserved != 1)  || (fmt_id_os->dwOffset !=0x30) )\r
+       {\r
+               printf("Not a valid properties set header in file %s\n", prop_file_name);\r
+               fclose(prop_file);\r
+               return NULL;\r
+       }\r
+\r
+       status=readbytes(prop_file, (char*)psect_header, sizeof(PROPERTYSECTIONHEADER));\r
+\r
+       psect_header = (PROPERTYSECTIONHEADER *)xrealloc(psect_header, psect_header->cbSection);\r
+       section_buff = (char*)psect_header;\r
+\r
+       status=readbytes(prop_file, (char*)(psect_header->rgPropIDOffset), \r
+                                               psect_header->cbSection - sizeof(PROPERTYSECTIONHEADER));\r
+\r
+       property_set = ole_property_set_new(psect_header->cProperties);\r
+       memcpy(property_set->fmtid, &(fmt_id_os->fmtid), 16);\r
+       memcpy(property_set->clsid, &(prop_header->clsid), 16);\r
+       property_set->OSKind = *((short int*)( &(prop_header->dwOSVer)   ) +1);\r
+       property_set->OSVer =  *((short int*)( &(prop_header->dwOSVer)   ));\r
+\r
+\r
+       // We cant rely on pointer order matching data order,\r
+       // so we need to do a little extra work to find the start of the next data\r
+       for (i=0; i< psect_header->cProperties ; i++)\r
+       {\r
+               next_start=psect_header->cbSection; //ie end of the buffer\r
+               for(j=0; j<psect_header->cProperties; j++)\r
+                       if(  ( psect_header->rgPropIDOffset[i].dwOffset < psect_header->rgPropIDOffset[j].dwOffset )\r
+                                && ( psect_header->rgPropIDOffset[j].dwOffset < next_start) )\r
+                               next_start = psect_header->rgPropIDOffset[j].dwOffset;\r
+\r
+               property_set->pPropList[i].buflen\r
+                       = next_start\r
+                       - psect_header->rgPropIDOffset[i].dwOffset\r
+                       -4;\r
+       }\r
+\r
+\r
+       for (i=0; i< psect_header->cProperties; i++)\r
+       {\r
+               property_set->pPropList[i].propid = psect_header->rgPropIDOffset[i].propid;\r
+               \r
+//             property_set->pPropList[i].buf \r
+//                     = section_buff + psect_header->rgPropIDOffset[i].dwOffset  + 4;\r
+\r
+               property_set->pPropList[i].buf = (char*)xmalloc(property_set->pPropList[i].buflen);\r
+               memcpy(property_set->pPropList[i].buf,\r
+                               section_buff + psect_header->rgPropIDOffset[i].dwOffset  + 4,\r
+                               property_set->pPropList[i].buflen);\r
+\r
+               property_set->pPropList[i].dwType =  *((DWORD*)(section_buff + psect_header->rgPropIDOffset[i].dwOffset));\r
+       }\r
+\r
+       for (i=0; i< property_set->cProps; i++)\r
+               if (property_set->pPropList[i].propid==0)\r
+                       property_set->dict=read_dictionary(property_set->pPropList[i].dwType, \r
+                                                               property_set->pPropList[i].buf, \r
+                                                               property_set->pPropList[i].buflen);\r
+\r
+       fclose(prop_file);\r
+       xfree(prop_header);\r
+       xfree(psect_header);\r
+       xfree(fmt_id_os);\r
+\r
+       return property_set;    \r
+}\r
+\r
+struct ole_property_set * read_ole_properties(char* source_file_name, char* properties_file_name)\r
+{\r
+       char * prop_file_name;\r
+       struct ole_property_set * strips_property_set=NULL;\r
+       struct ole_property_set * summary_property_set=NULL;\r
+       \r
+       if ( (source_file_name==NULL) && (properties_file_name==NULL) )\r
+               return NULL;\r
+\r
+       if (source_file_name!=NULL)\r
+               prop_file_name = (char*)xmalloc(strlen(source_file_name)+40);\r
+       else \r
+               prop_file_name = properties_file_name;\r
+\r
+       strcpy(prop_file_name, source_file_name);\r
+       strcpy(prop_file_name + strlen(prop_file_name), ".Contents\\");\r
+       strcpy(prop_file_name + strlen(prop_file_name), OLE_PROP_STREAM);\r
+       strips_property_set = read_ole_properties2(prop_file_name);\r
+       if (opts.verbose_flag>3)\r
+       {\r
+               printf("printing properties from %s\n",OLE_PROP_STREAM);\r
+               print_ole_properties(strips_property_set);\r
+       }\r
+\r
+       // We dont really need this next property set,\r
+       // but it may be interesting for debuging\r
+       if ( (source_file_name != NULL) && (opts.verbose_flag>3) )\r
+       {\r
+               strcpy(prop_file_name, source_file_name);\r
+               strcpy(prop_file_name + strlen(prop_file_name), ".Contents\\.SummaryInformation");\r
+               summary_property_set = read_ole_properties2(prop_file_name);\r
+               printf("printing properties from .SummaryInformation\n");\r
+               print_ole_properties(summary_property_set);\r
+       }\r
+\r
+       debug_pause();\r
+\r
+       xfree(prop_file_name);\r
+       ole_property_set_delete(summary_property_set);\r
+\r
+       return strips_property_set;\r
+}\r
diff --git a/st2gpx/src/properties.h b/st2gpx/src/properties.h
new file mode 100644 (file)
index 0000000..c8d398d
--- /dev/null
@@ -0,0 +1,72 @@
+/*\r
+       properties.h\r
+\r
+       Extract data from MS Streets & Trips .est and Autoroute .axe files in GPX format.\r
+\r
+    Copyright (C) 2003 James Sherring, james_sherring@yahoo.com\r
+\r
+    This program is free software; you can redistribute it and/or modify\r
+    it under the terms of the GNU General Public License as published by\r
+    the Free Software Foundation; either version 2 of the License, or\r
+    (at your option) any later version.\r
+\r
+    This program is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+\r
+    You should have received a copy of the GNU General Public License\r
+    along with this program; if not, write to the Free Software\r
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA\r
+\r
+\r
+       This app depends on istorage & istorage-make from Pabs (pabs3@zip.to)\r
+       and James Clark's Expat xml parser from http://www.libexpat.org/.\r
+\r
+*/\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+\r
+typedef unsigned long DWORD;\r
+\r
+typedef struct dictionary \r
+{\r
+    DWORD    cEntries;        // Count of entries in the list.\r
+       // array of propids\r
+    DWORD *  ent_propid;  // Property ID\r
+       // This next is an array of pointers into properties value,\r
+       // with the string length preceeding (ie X->ent_cb == X->ent_sz -4)\r
+    char **  ent_sz;  // Zero-terminated string. Code page as indicated. \r
+} tag_dictionary;\r
+\r
+typedef struct ole_property\r
+{\r
+       DWORD   propid;\r
+    DWORD   dwType;      // type tag\r
+       int             buflen;\r
+       char*   buf;\r
+} tag_ole_property;\r
+\r
+typedef struct ole_property_set\r
+{\r
+//     FMTID  fmtid ;       // semantic name of a section\r
+       char   fmtid[16];       // semantic name of a section\r
+       char   clsid[16];               // clsid for the creating program\r
+       int    OSKind;                  // The OS that created the prop-set\r
+       int    OSVer;   \r
+       unsigned int       cProps;\r
+       struct dictionary * dict;\r
+       struct ole_property * pPropList;\r
+} tag_ole_property_set;\r
+\r
+struct ole_property_set * read_ole_properties(char* source_file_name, char* properties_file_name);\r
+void ole_property_set_delete(struct ole_property_set * props);\r
+struct ole_property * get_propterty(struct ole_property_set * props, DWORD propid);\r
+\r
+\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
index 2143019ee1e4ebd0974af9ebef87fc763fdb2c38..7bc4f7b30a154ce84371c7e256e8d91e67965a5f 100644 (file)
     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA\r
 */\r
 \r
-#import "c:\program files\common files\system\ado\msado15.dll" rename ( "EOF", "adoEOF" )\r
+// FIXME (re)use a single db conection for all recordsets for improved performance\r
+\r
+// for vt type values see http://www.canaimasoft.com/f90VB/OnlineManuals/UserManual/TH_99.htm\r
+\r
+//#import "c:\program files\common files\system\ado\msado15.dll" rename ( "EOF", "adoEOF" )\r
 //#import <msado15.dll> rename ( "EOF", "adoEOF" )\r
+#include "msado15.tlh"\r
+#include "msado15.tli"\r
 \r
 #include <windows.h>\r
 #include <initguid.h>  // Include only once in your application\r
-//#include "adoid.h"     // ADO GUID's\r
-//#include "adoint.h"    // ADO Classes, enums, etc.\r
 #include <oleauto.h>   // for sysstringlength\r
 #include <stdio.h>\r
-//#include <stdlib.h>\r
-//#include <malloc.h>\r
-//#include <memory.h>\r
 #include <string.h>\r
-\r
+#include "st2gpx.h"\r
+#include "gpx.h"\r
 #include "pushpins.h"\r
+#include "ppinutil.h"\r
+#include "contents.h"\r
+\r
 \r
 struct InitOle {\r
 InitOle()  { ::CoInitialize(NULL); }\r
 ~InitOle() { ::CoUninitialize();   }\r
 } _init_InitOle_;\r
 \r
-int verbose_flag;\r
 \r
-void * xmalloc(size_t size)\r
+VARIANT val2variant(unsigned short fieldtype, void* stor_var)\r
 {\r
-       void *obj = malloc(size);\r
-       if (!obj)\r
-       {\r
-               fprintf(stderr, "Unable to allocate %d bytes of memory.\n", size);\r
-       }\r
-       return obj;\r
-}\r
+       VARIANT vt_val;\r
+       vt_val.vt=fieldtype;\r
 \r
-LPWSTR wstr2cpy(BSTR wstr)\r
-{\r
-       int len=wcslen(wstr);\r
-       LPWSTR newstr=(LPWSTR)xmalloc((len+1)*sizeof(WCHAR));\r
-       wcscpy(newstr, wstr);\r
-       return newstr;\r
-}\r
+       // not sure if this is neccessary\r
+       VariantInit(&vt_val);\r
 \r
-char* wstr2str(BSTR wstr)\r
-// there must be a better way to do this\r
-{\r
-       int len;\r
-       int i;\r
-       char* newstr=NULL;\r
-       // call to get length\r
-       len = WideCharToMultiByte(\r
-                               CP_THREAD_ACP,\r
-                               0,\r
-                               wstr,\r
-                               -1,\r
-                               newstr,\r
-                               0, \r
-                               NULL,\r
-                               0);\r
-       if(len==0)\r
+       switch (fieldtype)\r
        {\r
-               //printf("wide2normal got length %d\n", len);\r
-               len=wcslen(wstr);\r
-               //printf("wide2normal cheated and got length %d\n", len);\r
-       };\r
-       newstr = (char*)xmalloc((len+1)*sizeof(char));\r
-       // now call to set string\r
-       len = WideCharToMultiByte(\r
-                               CP_THREAD_ACP,\r
-                               0,\r
-                               wstr,\r
-                               -1,\r
-                               newstr,\r
-                               len, \r
-                               NULL,\r
-                               0);\r
-       //printf("wide2normal copied %d chars and got string %s\n", len, newstr);\r
-       if (len==0)\r
-       {\r
-               len=wcslen(wstr);\r
-               for(i=0; i<len; i++)\r
-                       newstr[i]=wstr[i];\r
-               newstr[len]=0;\r
-               //printf("wide2normal cheated to get string %s\n", newstr);\r
+       case VT_I4:\r
+               vt_val.lVal = *(int*)stor_var;\r
+               vt_val.vt=fieldtype;\r
+               break;\r
+\r
+       case VT_I2:\r
+               vt_val.iVal = *(short int*)stor_var ;\r
+               vt_val.vt=fieldtype;\r
+               break;\r
+\r
+       case VT_BSTR:\r
+               // Note that stor_var must be a pointer to a null-terminated char* string (not unicode)\r
+               if ( (stor_var==NULL) || (strlen((char*)stor_var)==0) )\r
+                       vt_val.vt=VT_NULL;\r
+               else\r
+               {\r
+                       vt_val.vt=fieldtype;\r
+                       vt_val.bstrVal = _com_util::ConvertStringToBSTR((char*)stor_var);\r
+               }\r
+               break;\r
+\r
+/*     case (VT_ARRAY | VT_UI1): // 8192 | 17 = 8209\r
+               SafeArrayGetLBound(vt_val.parray, 1, &lbound);\r
+               SafeArrayGetUBound(vt_val.parray, 1, &ubound);\r
+               if( (SafeArrayGetDim(vt_val.parray)!=1) || (lbound !=0) )\r
+               {\r
+                       printf("got safe array of short ints, with %d dimensions and bounds %d:%d\n", \r
+                               SafeArrayGetDim(vt_val.parray), lbound, ubound);\r
+                       printf("Sadly, I was expecting 1 dimention and lower bound of zero, so I will ignore this array.\n");\r
+                       break;\r
+               }\r
+               for(elmt=lbound; elmt<ubound+1; elmt++)\r
+               {\r
+                       SafeArrayGetElement(vt_val.parray, &elmt, &array_val);\r
+                       //printf("array(%d)=%d\n", elmt, array_val);\r
+                       ((char*)stor_var)[elmt-lbound]=array_val;\r
+               }\r
+               //debug_pause();\r
+               break;\r
+*/\r
+       default:\r
+               fprintf(stderr,"Unsupported type %d, setting DB value to NULL\n", vt_val.vt);\r
+               vt_val.vt=VT_NULL;\r
        }\r
-       return newstr;\r
-}\r
 \r
-void readfield(VARIANT vt_val, unsigned short fieldtype, void* stor_var)\r
+       return vt_val;\r
+};\r
+\r
+void variant2val(VARIANT vt_val, unsigned short fieldtype, void* stor_var)\r
 {\r
-//     int len=0;\r
-       LPWSTR tempwstr=NULL;\r
        char* shortstr=NULL;\r
-//     int status;\r
-//     int i;\r
+       long lbound;\r
+       long ubound;\r
+       long elmt;\r
+       // should be a short?\r
+       char array_val=0;\r
 \r
        if ((vt_val.vt == fieldtype) || ( (fieldtype==VT_BSTR) && (vt_val.vt==VT_NULL)))\r
        {\r
                switch (vt_val.vt)\r
                {\r
                case VT_I4:\r
-                       *(long*)stor_var = vt_val.lVal;\r
+                       *(int*)stor_var = vt_val.lVal;\r
                        break;\r
 \r
                case VT_I2:\r
-                       *(int*)stor_var = vt_val.iVal;\r
+                       // FIXME should I do this as short?\r
+                       *(short int*)stor_var = vt_val.iVal;\r
                        break;\r
 \r
                case VT_BSTR:\r
-                       // FIXME handle bstr properly\r
-                       tempwstr = wstr2cpy(vt_val.bstrVal);\r
-                       //wprintf(L"got temp str%s\n",tempwstr);\r
-\r
-                       shortstr = wstr2str(vt_val.bstrVal);\r
-                       //printf("got short temp str%s\n",shortstr);\r
-                       \r
-                       //*(void**)stor_var = (void*)tempwstr;\r
+                       //shortstr = wstr2str(vt_val.bstrVal);\r
+                       shortstr = _com_util::ConvertBSTRToString(vt_val.bstrVal);\r
                        *(char**)stor_var = shortstr;\r
-                       //printf("verified short temp str%s\n", *(char**)stor_var);\r
                        break;\r
 \r
                case VT_NULL:\r
                        // expected string, this is null \r
                        // so return empty string\r
-\r
-                       shortstr = (char*)xmalloc(sizeof(char));\r
+                       shortstr = (char*)xmalloc(1);\r
                        shortstr[0]=0;\r
-                       //printf("got short temp str%s\n",shortstr);\r
-                       \r
                        *(char**)stor_var = shortstr;\r
                        break;\r
+               case (VT_ARRAY | VT_UI1): // 8192 | 17 = 8209\r
+                       SafeArrayGetLBound(vt_val.parray, 1, &lbound);\r
+                       SafeArrayGetUBound(vt_val.parray, 1, &ubound);\r
+                       if( (SafeArrayGetDim(vt_val.parray)!=1) || (lbound !=0) )\r
+                       {\r
+                               printf("got safe array of short ints, with %d dimensions and bounds %d:%d\n", \r
+                                       SafeArrayGetDim(vt_val.parray), lbound, ubound);\r
+                               printf("Sadly, I was expecting 1 dimention and lower bound of zero, so I will ignore this array.\n");\r
+                               break;\r
+                       }\r
+                       for(elmt=lbound; elmt<ubound+1; elmt++)\r
+                       {\r
+                               SafeArrayGetElement(vt_val.parray, &elmt, &array_val);\r
+                               //printf("array(%d)=%d\n", elmt, array_val);\r
+                               ((char*)stor_var)[elmt-lbound]=array_val;\r
+                       }\r
+                       //debug_pause();\r
+                       break;\r
                default:\r
-                       fprintf(stderr,"Unsupported type, unable to read from DB\n");\r
+                       fprintf(stderr,"Unsupported type %d, unable to read from DB\n", vt_val.vt);\r
                }\r
-\r
        }\r
        else\r
        {\r
                fprintf(stderr,"Type mismatch when reading from DB, expected type %d read type %d\n", \r
                        fieldtype, vt_val.vt);\r
+               debug_pause();\r
        }\r
 \r
 }\r
 \r
-// EXTERN_C \r
-EXTERN_C void read_ppin_list(char* ppin_file_name)\r
+EXTERN_C struct pushpin_safelist * read_pushpins(char* ppin_file_name)\r
 {\r
 \r
        struct pushpin * ppin;\r
        int ppinnum=0;\r
-       \r
+       int UdmDataId=0;\r
+       struct pushpin_safelist * ppplist = pushpin_safelist_new();\r
+       // number of pushpins to allocate pointer-array storage for, this is incremented as needed\r
+       int ppin_list_alloc_size=100;\r
+       char * ppin_sql = NULL;\r
+       char * UDM_sql = NULL;\r
+\r
+       ppplist->pushpin_list = (struct pushpin **)xmalloc(ppin_list_alloc_size*sizeof(struct pushpin *));\r
+\r
+       if (opts.st_version_num<9)\r
+               ppin_sql = "SELECT UD_Secondary.UdId, UD_Secondary.UdName, UD_Secondary.NoteShort, UD_Secondary.NoteLong, UD_Main.Grid, UD_Main.Precision, UD_Main.MatchId, UD_Main.MOBBId FROM UD_Main INNER JOIN UD_Secondary ON UD_Main.UdId = UD_Secondary.UdId";\r
+       else\r
+               ppin_sql = "SELECT UdId, UdName, NoteShort, NoteLong, Grid, Precision, MatchId, MOBBId FROM UD_Main";\r
+\r
        try \r
        {\r
                HRESULT hr = S_OK;\r
                ADODB::_RecordsetPtr rs; \r
                char cnstr[500];\r
-               char sqlstr[] = "SELECT UD_Secondary.UdId, UD_Secondary.UdName, UD_Secondary.NoteShort, UD_Secondary.NoteLong, UD_Main.Grid, UD_Main.Precision FROM UD_Main INNER JOIN UD_Secondary ON UD_Main.UdId = UD_Secondary.UdId";\r
                sprintf(cnstr, "PROVIDER=Microsoft.Jet.OLEDB.4.0;data source=%s; Jet OLEDB:Database Password=Geo80;", ppin_file_name);\r
 \r
                hr = rs.CreateInstance( __uuidof( ADODB::Recordset ) );\r
-               hr = rs->Open(sqlstr, \r
+\r
+               // *****************\r
+               // Read GEODB_LastId\r
+               // *****************\r
+\r
+               // FIXME read dbversion, use that instead of file version for setting sql\r
+\r
+               // *************\r
+               // read pushpins\r
+               // *************\r
+\r
+               hr = rs->Open(ppin_sql, \r
                                  cnstr, \r
                                          ADODB::adOpenForwardOnly, \r
                                          ADODB::adLockReadOnly, \r
                                          -1 );\r
-               hr = rs->MoveFirst();\r
+\r
                while ((rs->adoEOF == FALSE))\r
                {\r
-                       ppin = (struct pushpin *)xmalloc(sizeof(struct pushpin));\r
+                       ppin = pushpin_new();\r
+\r
+                       variant2val(rs->Fields->GetItem("UdId")->Value,         VT_I4,  &(ppin->UdId));\r
+                       variant2val(rs->Fields->GetItem("UdName")->Value,       VT_BSTR,&(ppin->UdName));\r
+                       variant2val(rs->Fields->GetItem("Grid")->Value,         VT_I4,  &(ppin->Grid));\r
+                       variant2val(rs->Fields->GetItem("Precision")->Value,VT_I4,      &(ppin->Precision));\r
+                       variant2val(rs->Fields->GetItem("NoteShort")->Value,VT_BSTR,&(ppin->NoteShort));\r
+                       variant2val(rs->Fields->GetItem("MatchId")->Value,      VT_I2,  &(ppin->MatchId));\r
+                       variant2val(rs->Fields->GetItem("MOBBId")->Value,       VT_I4,  &(ppin->MOBBId));\r
 \r
-                       readfield(rs->Fields->GetItem("UdId")->Value,           VT_I4,  &(ppin->UdId));\r
-                       readfield(rs->Fields->GetItem("UdName")->Value,         VT_BSTR,&(ppin->UdName));\r
-                       readfield(rs->Fields->GetItem("Grid")->Value,           VT_I4,  &(ppin->Grid));\r
-                       readfield(rs->Fields->GetItem("Precision")->Value,      VT_I4,  &(ppin->Precision));\r
-                       readfield(rs->Fields->GetItem("NoteShort")->Value,      VT_BSTR,&(ppin->NoteShort));\r
+                       str2ascii(ppin->UdName);\r
+                       str2ascii(ppin->NoteShort);\r
 \r
-                       if (verbose_flag > 3)\r
+                       if (opts.verbose_flag > 3)\r
                                printf("Read pushpin UdId=%d, UdName=%s, Grid=%d, Precision=%d, NoteShort=%s\n", \r
                                        ppin->UdId, ppin->UdName, \r
                                        ppin->Grid, ppin->Precision, ppin->NoteShort);\r
-\r
-                       ppin_list[ppinnum]=ppin;\r
-                       ppinnum++;\r
-                       if (ppinnum>MAX_PUSHPINS-1)\r
+                       // what are the valid matchIds?\r
+                       if (ppin->MatchId==4)\r
                        {\r
-                               printf("Exceeded maximun number of pushpins (I should fix this)\n");\r
-                               break;\r
+                               printf("Read unmatched pushpin UdId=%d, UdName=%s, Grid=%d, Precision=%d, NoteShort=%s\n", \r
+                                       ppin->UdId, ppin->UdName, \r
+                                       ppin->Grid, ppin->Precision, ppin->NoteShort);\r
+                               printf("Discarding this pushpin because it is not geocoded (i.e. not matched to map).\n");\r
+                               pushpin_delete(ppin);\r
+                       }\r
+                       else\r
+                       {\r
+                               ppplist->pushpin_list[ppinnum]=ppin;\r
+                               ppinnum++;\r
+                               if (ppinnum>ppin_list_alloc_size-1)\r
+                               {\r
+                                       ppin_list_alloc_size += 100;\r
+                                       ppplist->pushpin_list = (struct pushpin **)xrealloc(ppplist->pushpin_list, ppin_list_alloc_size*sizeof(struct pushpin *));\r
+                               }\r
                        }\r
-\r
                        hr = rs->MoveNext();\r
                }\r
                hr = rs->Close();\r
-               rs = NULL;\r
+\r
+               // *************\r
+               // read UDM_Data\r
+               // *************\r
+\r
+               if (opts.explore_flag)\r
+               {\r
+                       UDM_sql = "Select UdmDataId, UdmData from UDM_Data";\r
+\r
+                       hr = rs->Open(UDM_sql, \r
+                                                 cnstr, \r
+                                                 ADODB::adOpenForwardOnly, \r
+                                                 ADODB::adLockReadOnly, \r
+                                                 -1 );\r
+\r
+                       while ((rs->adoEOF == FALSE))\r
+                       {\r
+                               variant2val(rs->Fields->GetItem("UdmDataId")->Value, VT_I4, &UdmDataId);\r
+                               if ( (UdmDataId<0) || (UdmDataId>3) )\r
+                               {\r
+                                       printf("*** Unexpected UdmDataId=%d\n", UdmDataId);\r
+                                       break;\r
+                               }\r
+                               \r
+                               ppplist->UDM_Data_length[UdmDataId] = rs->Fields->GetItem("UdmData")->ActualSize; \r
+                               ppplist->UDM_Data[UdmDataId]=(char*)xmalloc(ppplist->UDM_Data_length[UdmDataId]);\r
+                               variant2val(rs->Fields->GetItem("UdmData")->Value, VT_ARRAY | VT_UI1, ppplist->UDM_Data[UdmDataId]);\r
+\r
+                               printf("In UDM_Data table, for UdId=%d got %d bytes of data\n",\r
+                                       UdmDataId,      ppplist->UDM_Data_length[UdmDataId]);\r
+                               printbuf(ppplist->UDM_Data[UdmDataId], ppplist->UDM_Data_length[UdmDataId]);\r
+\r
+                               hr = rs->MoveNext();\r
+                       }\r
+               hr = rs->Close();\r
+               }\r
+\r
+       rs = NULL;\r
+\r
        }\r
        catch( _com_error &e)\r
        {\r
         _bstr_t bstrSource(e.Source());\r
-        _bstr_t bs =  _bstr_t(" Error: ") + _bstr_t(e.Error()) + _bstr_t(" Msg: ") \r
+        _bstr_t bs =  _bstr_t("*** Exception: ") + _bstr_t(e.Error()) + _bstr_t(" Msg: ") \r
+            + _bstr_t(e.ErrorMessage()) + _bstr_t(" Description: ") \r
+            + _bstr_t(e.Description());\r
+               \r
+               wprintf(bs);\r
+               _flushall();\r
+        \r
+        if (opts.verbose_flag>4)\r
+                       MessageBox(0,bs,bstrSource, MB_OK);\r
+    }  \r
+\r
+       if (opts.verbose_flag > 1)\r
+               printf("Read %d pushpins from %s.\n", ppinnum, ppin_file_name);\r
+\r
+       ppplist->num_pushpins=ppinnum;\r
+       return ppplist;\r
+}\r
+\r
+EXTERN_C void write_pushpins_from_gpx(char* ppin_file_name, \r
+                                                                         struct gpx_data * all_gpx, \r
+                                                                         struct contents * conts,\r
+                                                                         char* conts_file_name)\r
+{\r
+       short int DbVersion=0;\r
+       int LastSetId=0;\r
+       long LastUserDataId=0;\r
+       long thisfirstUserDataId=0;\r
+       long thisUserDataId=0;\r
+       char* sql;\r
+       char* sql2;\r
+\r
+       // nothing to write\r
+       if (all_gpx->wpt_list_count==0)\r
+               return;\r
+\r
+       try \r
+       {\r
+               HRESULT hr = S_OK;\r
+               ADODB::_RecordsetPtr rs; \r
+               ADODB::_RecordsetPtr rs2; \r
+               char cnstr[500];\r
+               sprintf(cnstr, "PROVIDER=Microsoft.Jet.OLEDB.4.0;data source=%s; Jet OLEDB:Database Password=Geo80;", ppin_file_name);\r
+\r
+               hr = rs.CreateInstance( __uuidof( ADODB::Recordset ) );\r
+\r
+               // *****************\r
+               // Read GEODB_LastId\r
+               // *****************\r
+\r
+               sql = "select DbVersion, LastSetId, LastUserDataId from GEODB_LastId";\r
+               hr = rs->Open(sql, \r
+                                 cnstr, \r
+                                         ADODB::adOpenKeyset, \r
+                                         ADODB::adLockOptimistic, \r
+                                         -1 );\r
+\r
+               variant2val(rs->Fields->GetItem("DbVersion")->Value,            VT_I2,  &DbVersion);\r
+               variant2val(rs->Fields->GetItem("LastSetId")->Value,            VT_I4,  &LastSetId);\r
+               variant2val(rs->Fields->GetItem("LastUserDataId")->Value,       VT_I4,  &LastUserDataId);\r
+\r
+               printf("Got DbVersion=%d, LastSetId=%d and LastUserDataId=%d\n", DbVersion, LastSetId, LastUserDataId);\r
+\r
+               // *****************\r
+               // update LastSetId, LastUserDataId in GEODB_LastId\r
+               // *****************\r
+\r
+               // Later we might import pushpins as different sets, \r
+               // but for now we just import as one set\r
+\r
+               LastSetId += 1;\r
+               thisfirstUserDataId = LastUserDataId +1;\r
+               LastUserDataId += all_gpx->wpt_list_count;\r
+\r
+               rs->Fields->GetItem("LastSetId"     )->Value =  val2variant(VT_I4,      &LastSetId);\r
+               rs->Fields->GetItem("LastUserDataId")->Value =  val2variant(VT_I4,      &LastUserDataId);\r
+\r
+               rs->Update();\r
+               hr = rs->Close();\r
+               //printf("Updated LastSetId, LastUserDataId in GEODB_LastId\n");\r
+\r
+\r
+               // ******************\r
+               // Write all pushpins\r
+               // ******************\r
+\r
+               if (opts.st_version_num<9)\r
+               {\r
+                       sql = "Select UdId, SetId, Grid, Precision, MatchId, MOBBId, SourceUdId from UD_Main";\r
+                       sql2 = "Select UdId, NoteTypeId, GeocodeHierarchy, GeocodeContext, UdName, NoteShort, NoteLong from UD_Secondary";\r
+                       hr = rs->Open(sql, \r
+                                 cnstr, \r
+                                         ADODB::adOpenKeyset, \r
+                                         ADODB::adLockOptimistic, \r
+                                         -1 );\r
+                       hr = rs2.CreateInstance( __uuidof( ADODB::Recordset ) );\r
+                       hr = rs2->Open(sql2, \r
+                                                 cnstr, \r
+                                                 ADODB::adOpenKeyset, \r
+                                                 ADODB::adLockOptimistic, \r
+                                                 -1 );\r
+               }\r
+               else\r
+               {\r
+                       sql = "Select UdId, SetId, Grid, Precision, MatchId, MOBBId, SourceUdId, NoteTypeId, GeocodeHierarchy, GeocodeContext, UdName, NoteShort, NoteLong from UD_Main";\r
+                       // maybe we have to do this later, when rs is set?\r
+                       hr = rs->Open(sql, \r
+                                 cnstr, \r
+                                         ADODB::adOpenKeyset, \r
+                                         ADODB::adLockOptimistic, \r
+                                         -1 );\r
+               }\r
+\r
\r
+               int w;\r
+               struct gpxpt * gpt;\r
+               struct grid_point gridpt;\r
+               long lzero=0;\r
+               short int sizero=0;\r
+               short int sione=1;\r
+               short int sitwo=2;\r
+\r
+               // do for each wpt\r
+               for(w=0; w<all_gpx->wpt_list_count; w++)\r
+               {\r
+                       if (opts.st_version_num<9)\r
+                       {\r
+                               rs->AddNew();\r
+                               rs2->AddNew();\r
+                       }\r
+                       else\r
+                       {\r
+                               rs->AddNew();\r
+                               rs2 = rs;\r
+                       }\r
+\r
+                       thisUserDataId=thisfirstUserDataId+w;\r
+                       gpt = all_gpx->wpt_list[w];\r
+                       gridpt=latlon2grid(gpt->lat, gpt->lon);\r
+\r
+                       //printf("writing ppin with thisUserDataId=%d, gpt->name=%s\n", thisUserDataId, gpt->name);\r
+\r
+                       rs->Fields->GetItem("UdId"              )->Value = val2variant(VT_I4,   &thisUserDataId);\r
+                       rs->Fields->GetItem("SetId"             )->Value = val2variant(VT_I2,   &LastSetId);\r
+                       rs->Fields->GetItem("Grid"              )->Value = val2variant(VT_I4,   &(gridpt.grid));\r
+                       rs->Fields->GetItem("Precision" )->Value = val2variant(VT_I4,   &(gridpt.precision));\r
+                       rs->Fields->GetItem("MatchId"   )->Value = val2variant(VT_I2,   &sitwo);\r
+                       rs->Fields->GetItem("MOBBId"    )->Value = val2variant(VT_I4,   &lzero);\r
+                       rs->Fields->GetItem("SourceUdId")->Value = val2variant(VT_I4,   &lzero);\r
+\r
+                       if (opts.st_version_num<9)\r
+                               rs->Update();\r
+\r
+                       rs2->Fields->GetItem("UdId"             )->Value = val2variant(VT_I4,  &thisUserDataId);\r
+                       rs2->Fields->GetItem("UdName"   )->Value = val2variant(VT_BSTR,(gpt->name));\r
+                       rs2->Fields->GetItem("NoteTypeId")->Value = val2variant(VT_I2,  &sione);\r
+                       rs2->Fields->GetItem("NoteShort")->Value = val2variant(VT_BSTR,(gpt->desc));\r
+                       rs2->Fields->GetItem("GeocodeHierarchy")->Value = val2variant(VT_I2,  &sizero);\r
+                       rs2->Fields->GetItem("GeocodeContext"  )->Value = val2variant(VT_I4,  &lzero);\r
+                       // sometime I should support this\r
+                       // rs2->Fields->GetItem("NoteLong"   )->Value = val2variant(?,  NULL);\r
+                       rs2->Update();\r
+               }\r
+\r
+               if (opts.st_version_num<9)\r
+               {       \r
+                       rs->Close();\r
+                       rs2->Close();\r
+                       rs2 = NULL;\r
+               } \r
+               else\r
+               {\r
+                       rs->Close();\r
+               }\r
+\r
+               //printf("Inserted all pushpin records\n");\r
+\r
+               // **********************\r
+               // insert row in SET_Main, \r
+               // **********************\r
+\r
+               // SetId, SetName, UdCount, MatchedCount \r
+\r
+               // FIXME cant I use a compiler var for size of largest short?\r
+               if (LastSetId>(1<<15))\r
+                       printf("too many set ids!");\r
+               short int SetId=(short int)LastSetId;\r
+\r
+               char* SetName = all_gpx->data_source_name;\r
+               short int RenderMethod = 2;\r
+               short int GeocodeMethod = 5;\r
+               short int CreateMethod = 2;\r
+               short int GeometryType = 1;\r
+               long UdCount=all_gpx->wpt_list_count;\r
+               long MatchedCount=all_gpx->wpt_list_count;\r
+               long SkippedCount = 0;\r
+               long UnmatchedCount = 0;\r
+               long CounterUpdateMask=0;\r
+               short int ParentSetId=0;\r
+               short int IsRendered=-1;\r
+               long Z_Order=0; //5000;\r
+               long GeocodeCtxt=39070; // ???\r
+               int HLnkSrc=3;\r
+               long HLnkColId=0;\r
+\r
+               if(opts.st_version_num<9)\r
+                       sql = "SELECT SetId, SetName, RenderMethod, GeocodeMethod, CreateMethod, GeometryType, UdCount, MatchedCount, SkippedCount, UnmatchedCount, CounterUpdateMask, ParentSetId, IsRendered, Z_Order, GeocodeCtxt FROM SET_Main";\r
+               else\r
+                       sql = "SELECT SetId, SetName, RenderMethod, GeocodeMethod, CreateMethod, GeometryType, UdCount, MatchedCount, SkippedCount, UnmatchedCount, CounterUpdateMask, ParentSetId, IsRendered, Z_Order, GeocodeCtxt, HLnkSrc, HLnkColId FROM SET_Main";\r
\r
+               hr = rs->Open(sql, \r
+                             cnstr, \r
+                                 ADODB::adOpenKeyset, \r
+                                 ADODB::adLockOptimistic, \r
+                                 -1 );\r
+\r
+               rs->AddNew();\r
+\r
+               rs->Fields->GetItem("SetId"                             )->Value = val2variant(VT_I2,   &SetId);\r
+               rs->Fields->GetItem("SetName"                   )->Value = val2variant(VT_BSTR, SetName);\r
+               rs->Fields->GetItem("RenderMethod"              )->Value = val2variant(VT_I2,   &RenderMethod);\r
+               rs->Fields->GetItem("GeocodeMethod"             )->Value = val2variant(VT_I2,   &GeocodeMethod);\r
+               rs->Fields->GetItem("CreateMethod"              )->Value = val2variant(VT_I2,   &CreateMethod);\r
+               rs->Fields->GetItem("GeometryType"              )->Value = val2variant(VT_I2,   &GeometryType);\r
+               rs->Fields->GetItem("UdCount"                   )->Value = val2variant(VT_I4,   &UdCount);\r
+               rs->Fields->GetItem("MatchedCount"              )->Value = val2variant(VT_I4,   &MatchedCount);\r
+               rs->Fields->GetItem("SkippedCount"              )->Value = val2variant(VT_I4,   &SkippedCount);\r
+               rs->Fields->GetItem("UnmatchedCount"    )->Value = val2variant(VT_I4,   &UnmatchedCount);\r
+               rs->Fields->GetItem("CounterUpdateMask" )->Value = val2variant(VT_I4,   &CounterUpdateMask);\r
+               rs->Fields->GetItem("ParentSetId"               )->Value = val2variant(VT_I2,   &ParentSetId);\r
+               rs->Fields->GetItem("IsRendered"                )->Value = val2variant(VT_I2,   &IsRendered);\r
+               rs->Fields->GetItem("Z_Order"                   )->Value = val2variant(VT_I4,   &Z_Order);\r
+               rs->Fields->GetItem("GeocodeCtxt"               )->Value = val2variant(VT_I4,   &GeocodeCtxt);\r
+               \r
+               if(opts.st_version_num>8)\r
+               {\r
+                       rs->Fields->GetItem("HLnkSrc"           )->Value = val2variant(VT_I2,   &HLnkSrc);\r
+                       rs->Fields->GetItem("HLnkColId"         )->Value = val2variant(VT_I4,   &HLnkColId);\r
+               }\r
+               \r
+               rs->Update();\r
+               rs->Close();\r
+\r
+\r
+               // ***************************\r
+               // construct & update UDM_data\r
+               // ***************************\r
+\r
+               // we need to do this to show ppin name, info, symbol etc\r
+\r
+               // *******************\r
+               // COM / ADO  clean up \r
+               // *******************\r
+\r
+               rs = NULL;\r
+               if (rs2)\r
+                       rs2 = NULL;\r
+\r
+               // *****************\r
+               // update contents\r
+               // *****************\r
+\r
+               struct contents * mod_conts = contents_insert_ppinset(conts, (unsigned short)LastSetId);\r
+               if (mod_conts!=NULL)\r
+               {\r
+                       write_contents(mod_conts, conts_file_name);\r
+                       contents_delete(mod_conts);\r
+\r
+                       printf("Wrote %d waypoints as PushPins\n", all_gpx->wpt_list_count);\r
+                       debug_pause();\r
+               }\r
+               else\r
+                       printf("failed to successfully write pushpins, output is now corrupt.\n");\r
+        }\r
+       catch( _com_error &e)\r
+       {\r
+        _bstr_t bstrSource(e.Source());\r
+        _bstr_t bs =  _bstr_t("*** Exception: ") + _bstr_t(e.Error()) + _bstr_t(" Msg: ") \r
             + _bstr_t(e.ErrorMessage()) + _bstr_t(" Description: ") \r
             + _bstr_t(e.Description());\r
+               \r
+               wprintf(bs);\r
+               _flushall();\r
         \r
-        MessageBox(0,bs,bstrSource, MB_OK);\r
+//        if (opts.verbose_flag>4)\r
+                       MessageBox(0,bs,bstrSource, MB_OK);\r
     }  \r
+\r
 }\r
index e699a409fc2a5c88f87d67f759f16975b2ba9704..425391cec94449968a5509100a4de08836c6b53c 100644 (file)
 extern "C" {\r
 #endif\r
 \r
-#define MAX_PUSHPINS 5000\r
-\r
-// max size to be read from ppin memo fields\r
-#define MAX_PPIN_MEMO  1000\r
-\r
-typedef struct pushpin\r
-{\r
-       long UdId;\r
-       int SetId;\r
-       long Grid;\r
-       long Precision;\r
-//     dword RenderData;\r
-//     byte MatchId;\r
-//     long MOBBId;\r
-//     long SourceUdId;\r
-//     bool IsTerritory;\r
-//\r
-       char* UdName;   // max 128\r
-//     bool NoNameSearch;\r
-//     byte NoteTypeId;\r
-       char* NoteShort; // max 255\r
-//     char* NoteLong; // memo\r
-//     char* GeocodeShort; // max 255\r
-//     char* GeocodeLong; // memo\r
-//     byte GeocodeHierarchy; \r
-//     byte GeocodeContext; \r
-//     OLE Object EntityArray ????\r
-//\r
-// shouldn't include these two here because they are not part of the native pushpin definition\r
-       double lat;\r
-       double lon;\r
-} tag_pushpin;\r
-\r
-\r
-typedef struct pushpinset\r
-{\r
-       int SetId;\r
-       char* SetName; // max 128\r
-/*     byte RenderMethod;\r
-       byte GeocodeMethod;\r
-       byte CreateMethod;\r
-       byte GeometryType;\r
-       char[128] RenderData;\r
-       long UdCount;\r
-       long MatchedCount;\r
-       long SkippedCount;\r
-       long UnmatchedCount;\r
-       long CounterUpdateMask;\r
-       int ParentSetId;\r
-       bool IsRendered;\r
-       long Z_Order;\r
-       long GeocodeCtxt;\r
-       OLE Object ThemeRenderData\r
-       date/time LastGeocoded\r
-       char* DataSrcDescr; // memo\r
-       char[30] CurrencyData;\r
-*/\r
-} tag_pushpinset;\r
-\r
-//struct pushpin * ppin_list[MAX_PUSHPINS];\r
-struct pushpin * ppin_list[5000];\r
-\r
-//EXTERN_C\r
- void read_ppin_list(char* ppin_file_name);\r
-\r
-\r
+//EXTERN_C \r
+struct pushpin_safelist * read_pushpins(char* ppin_file_name);\r
+//EXTERN_C \r
+void write_pushpins_from_gpx(char* ppin_file_name, \r
+                                                                         struct gpx_data * all_gpx, \r
+                                                                         struct contents * conts,\r
+                                                                         char* conts_file_name);\r
 #ifdef __cplusplus\r
 } /* closing brace for extern "C" */\r
 #endif\r
diff --git a/st2gpx/src/readgpx.c b/st2gpx/src/readgpx.c
new file mode 100644 (file)
index 0000000..e9da430
--- /dev/null
@@ -0,0 +1,656 @@
+/*\r
+       readgpx.c\r
+\r
+       Extract data from MS Streets & Trips .est and Autoroute .axe files in GPX format.\r
+\r
+    Copyright (C) 2003 James Sherring, james_sherring@yahoo.com\r
+\r
+    This program is free software; you can redistribute it and/or modify\r
+    it under the terms of the GNU General Public License as published by\r
+    the Free Software Foundation; either version 2 of the License, or\r
+    (at your option) any later version.\r
+\r
+    This program is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+\r
+    You should have received a copy of the GNU General Public License\r
+    along with this program; if not, write to the Free Software\r
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA\r
+\r
+\r
+       This app depends on istorage & istorage-make from Pabs (pabs3@zip.to)\r
+       and James Clark's Expat xml parser from http://www.libexpat.org/.\r
+\r
+*/\r
+\r
+#include <stdio.h>\r
+#include <memory.h>\r
+#include <string.h>\r
+\r
+#include <expat.h>\r
+#include "gpx.h"\r
+#include "st2gpx.h"\r
+\r
+\r
+typedef void (*gpx_elm_start_handler)(void *, const char *, const char **);\r
+typedef void (*gpx_elm_end_handler)(void *, const char *);\r
+\r
+int current_main_element=0;\r
+int current_element=0;\r
+static XML_Char * cdata;\r
+static int cdata_length;\r
+\r
+//FILE* gpx_in_file=NULL;\r
+\r
+char * gpx_elem_name[] = \r
+{\r
+       "unknown-element",\r
+       "wpt",\r
+       "rte",\r
+       "rtept",\r
+       "trk",\r
+       "trkseg",\r
+       "trkpt",\r
+       "name",\r
+       "desc",\r
+       "src"\r
+};\r
+\r
+struct gpxpt * gpxpt_new()\r
+{\r
+       struct gpxpt * nw = (struct gpxpt *)xmalloc(sizeof(struct gpxpt));\r
+       nw->name=NULL;\r
+       nw->desc=NULL;\r
+       nw->lat=0;\r
+       nw->lon=0;\r
+       nw->elevation=0;\r
+       nw->use_elevation=0;\r
+       return nw;\r
+}\r
+\r
+void gpxpt_delete(struct gpxpt * pt)\r
+{\r
+       if(pt==NULL)\r
+               return;\r
+       xfree(pt->name);\r
+       xfree(pt->desc);\r
+       xfree(pt);\r
+}\r
+\r
+struct gpxpt * gpxpt_copy(struct gpxpt * otherpt)\r
+{\r
+       struct gpxpt * nw = (struct gpxpt *)xmalloc(sizeof(struct gpxpt));\r
+       nw->name=xmalloc(strlen(otherpt->name)+1);\r
+       strcpy(nw->name, otherpt->name);\r
+       nw->desc=xmalloc(strlen(otherpt->desc)+1);\r
+       strcpy(nw->desc, otherpt->desc);\r
+       nw->lat=otherpt->lat;\r
+       nw->lon=otherpt->lon;\r
+       nw->elevation=otherpt->elevation;\r
+       nw->use_elevation=otherpt->use_elevation;\r
+       return nw;\r
+}\r
+\r
+struct gpxpt * find_matching_wpt(struct gpx_data * dat, char* name)\r
+{\r
+       int i;\r
+       struct gpxpt * match = NULL;\r
+       for(i=0; i<dat->wpt_list_count; i++)\r
+               if(strcmp(name, dat->wpt_list[i]->name)==0)\r
+               {\r
+                       match = dat->wpt_list[i];\r
+                       break;\r
+               }\r
+       return match;\r
+}\r
+\r
+struct gpxrte * gpxrte_new()\r
+{\r
+       struct gpxrte * nw = (struct gpxrte *)xmalloc(sizeof(struct gpxrte));\r
+       nw->name=NULL;\r
+       nw->rtept_list=NULL;\r
+       nw->rtept_list_count=0;\r
+       return nw;\r
+}\r
+\r
+void gpxrte_delete(struct gpxrte * rte)\r
+{\r
+       int i;\r
+       if(rte==NULL)\r
+               return;\r
+       for (i=0; i<rte->rtept_list_count; i++)\r
+               gpxpt_delete(rte->rtept_list[i]);\r
+       xfree(rte->rtept_list);\r
+       xfree(rte->name);\r
+       xfree(rte);\r
+}\r
+\r
+struct gpxtrk * gpxtrk_new()\r
+{\r
+       struct gpxtrk * nw = (struct gpxtrk *)xmalloc(sizeof(struct gpxtrk));\r
+       nw->trkpt_list=NULL;\r
+       nw->trkpt_list_count=0;\r
+       return nw;\r
+}\r
+\r
+void gpxtrk_delete(struct gpxtrk * trk)\r
+{\r
+       int i;\r
+       if(trk==NULL)\r
+               return;\r
+       for (i=0; i<trk->trkpt_list_count; i++)\r
+               gpxpt_delete(trk->trkpt_list[i]);\r
+       xfree(trk->trkpt_list);\r
+       xfree(trk);\r
+}\r
+\r
+struct gpx_data * gpx_data_new()\r
+{\r
+       struct gpx_data * all_data = (struct gpx_data *)xmalloc(sizeof(struct gpx_data));\r
+       all_data->data_source_name=NULL;\r
+       all_data->wpt_list=NULL;\r
+       all_data->wpt_list_count=0;\r
+       all_data->rte_list=NULL;\r
+       all_data->rte_list_count=0;\r
+       all_data->trk_list=NULL;\r
+       all_data->trk_list_count=0;\r
+       return all_data;\r
+}\r
+\r
+void gpx_data_delete(struct gpx_data * data)\r
+{\r
+       int i;\r
+       if(data==NULL)\r
+               return;\r
+\r
+       xfree(data->data_source_name);\r
+       for (i=0; i<data->wpt_list_count; i++)\r
+               gpxpt_delete(data->wpt_list[i]);\r
+       for (i=0; i<data->rte_list_count; i++)\r
+               gpxrte_delete(data->rte_list[i]);\r
+       for (i=0; i<data->trk_list_count; i++)\r
+               gpxtrk_delete(data->trk_list[i]);\r
+       xfree(data->wpt_list);\r
+       xfree(data->rte_list);\r
+       xfree(data->trk_list);\r
+       xfree(data);\r
+}\r
+\r
+void print_wptlist(struct gpxpt ** wpt_list, int wpt_list_count)\r
+{\r
+       int i;\r
+       printf("Global waypoints:\n");\r
+       for (i=0; i<wpt_list_count; i++)\r
+               printf("wpt: lat=%f, lon=%f, name='%s', desc='%s'\n", \r
+                               wpt_list[i]->lat, wpt_list[i]->lon, wpt_list[i]->name, wpt_list[i]->desc);\r
+}\r
+\r
+void print_route(struct gpxrte * rte)\r
+{\r
+       int i;\r
+       printf("Route '%s' with %d route-points:\n", rte->name, rte->rtept_list_count);\r
+       for (i=0; i<rte->rtept_list_count; i++)\r
+               printf("rtept: lat=%f, lon=%f, name='%s', desc='%s'\n", \r
+                               (rte->rtept_list)[i]->lat, (rte->rtept_list)[i]->lon,\r
+                               (rte->rtept_list)[i]->name, (rte->rtept_list)[i]->desc);\r
+}\r
+\r
+void print_route_list(struct gpxrte ** rte_list, int rte_list_count)\r
+{\r
+       int i;\r
+       printf("Global route list with %d routes:\n", rte_list_count);\r
+       for (i=0; i<rte_list_count; i++)\r
+               print_route(rte_list[i]);\r
+}\r
+\r
+void print_track(struct gpxtrk * trk)\r
+{\r
+       int i;\r
+       printf("Track with %d track-points:\n", trk->trkpt_list_count);\r
+       for (i=0; i<trk->trkpt_list_count; i++)\r
+               printf("trkpt: lat=%f, lon=%f\n", \r
+                               trk->trkpt_list[i]->lat, trk->trkpt_list[i]->lon);\r
+}\r
+\r
+void print_track_list(struct gpxtrk ** trk_list, int trk_list_count)\r
+{\r
+       int i;\r
+       printf("Global track list with %d tracks:\n", trk_list_count);\r
+       for (i=0; i<trk_list_count; i++)\r
+               print_track(trk_list[i]);\r
+}\r
+\r
+void print_gpx_data(struct gpx_data * all_data)\r
+{\r
+       print_wptlist(all_data->wpt_list, all_data->wpt_list_count);\r
+       print_route_list(all_data->rte_list, all_data->rte_list_count);\r
+       print_track_list(all_data->trk_list, all_data->trk_list_count);\r
+}\r
+\r
+char* get_att(char* match, const char **atts)\r
+{                \r
+       const char **avp = &atts[0];\r
+       while (*avp) { \r
+               if (strcmp(avp[0], match) == 0) \r
+                       return (char *)avp[1];\r
+               avp+=2;\r
+       }\r
+       return NULL;\r
+}\r
+\r
+void startunkn(void *userData, const char *name, const char **atts)\r
+{\r
+       if(opts.verbose_flag > 3)\r
+               printf("ignoring start element name %s\n", name);\r
+}\r
+\r
+void endunkn(void *userData, const char *name)\r
+{\r
+       if(opts.verbose_flag > 3)\r
+               printf("ignoring end element name %s\n", name);\r
+}\r
+\r
+void startwpt(void *userData, const char *name, const char **atts)\r
+{\r
+       struct gpx_data * dat = (struct gpx_data *)userData;\r
+\r
+       if (current_main_element!=0)\r
+       {\r
+               printf("unexpected <wpt> element\n");\r
+               debug_pause();\r
+               exit(1);\r
+       }\r
+       current_main_element=GPX_ELEM_TYPE_WPT;\r
+\r
+       dat->wpt_list=(struct gpxpt **)xrealloc(dat->wpt_list, (dat->wpt_list_count+1)*sizeof(struct gpxpt *));\r
+       dat->wpt_list[dat->wpt_list_count] = gpxpt_new();\r
+\r
+       sscanf(get_att("lat", atts), "%lf", &(dat->wpt_list[dat->wpt_list_count]->lat));\r
+       sscanf(get_att("lon", atts), "%lf", &(dat->wpt_list[dat->wpt_list_count]->lon));\r
+       dat->wpt_list_count++;\r
+}\r
+\r
+void endwpt(void *userData, const char *name)\r
+{\r
+       if (current_main_element!=GPX_ELEM_TYPE_WPT)\r
+       {\r
+               printf("unexpected </wpt> element\n");\r
+               debug_pause();\r
+               exit(1);\r
+       }\r
+       current_main_element=0;\r
+}\r
+\r
+void startrte(void *userData, const char *name, const char **atts)\r
+{\r
+       struct gpx_data * dat = (struct gpx_data *)userData;\r
+\r
+       if (current_main_element!=0)\r
+       {\r
+               printf("unexpected <rte> element\n");\r
+               debug_pause();\r
+               exit(1);\r
+       }\r
+       current_main_element=GPX_ELEM_TYPE_RTE;\r
+\r
+       dat->rte_list=(struct gpxrte **)xrealloc(dat->rte_list, (dat->rte_list_count+1)*sizeof(struct gpxrte *));\r
+       dat->rte_list[dat->rte_list_count]=gpxrte_new();\r
+//     dat->rte_list[dat->rte_list_count]->name="{get route name from a following element}";\r
+       dat->rte_list_count++;\r
+}\r
+\r
+void endrte(void *userData, const char *name)\r
+{\r
+       if (current_main_element!=GPX_ELEM_TYPE_RTE)\r
+       {\r
+               printf("unexpected </rte> element\n");\r
+               debug_pause();\r
+               exit(1);\r
+       }\r
+       current_main_element=0;\r
+}\r
+\r
+void startrtept(void *userData, const char *name, const char **atts)\r
+{\r
+       struct gpx_data * dat = (struct gpx_data *)userData;\r
+       struct gpxrte * thisrte = dat->rte_list[dat->rte_list_count-1];\r
+\r
+       if (current_main_element!=GPX_ELEM_TYPE_RTE)\r
+       {\r
+               printf("unexpected <rtept> element\n");\r
+               debug_pause();\r
+               exit(1);\r
+       }\r
+       current_main_element=GPX_ELEM_TYPE_RTEPT;\r
+\r
+       thisrte->rtept_list=(struct gpxpt **)xrealloc(thisrte->rtept_list, \r
+                                                                                               (thisrte->rtept_list_count+1)*sizeof(struct gpxpt *));\r
+       thisrte->rtept_list[thisrte->rtept_list_count] = gpxpt_new();\r
+       sscanf(get_att("lat", atts), "%lf", &(thisrte->rtept_list[thisrte->rtept_list_count]->lat));\r
+       sscanf(get_att("lon", atts), "%lf", &(thisrte->rtept_list[thisrte->rtept_list_count]->lon));\r
+       thisrte->rtept_list_count++;\r
+}\r
+\r
+void endrtept(void *userData, const char *name)\r
+{\r
+       if (current_main_element!=GPX_ELEM_TYPE_RTEPT)\r
+       {\r
+               printf("unexpected </rtept> element\n");\r
+               debug_pause();\r
+               exit(1);\r
+       }\r
+       current_main_element=GPX_ELEM_TYPE_RTE;\r
+}\r
+\r
+void starttrk(void *userData, const char *name, const char **atts)\r
+{\r
+       struct gpx_data * dat = (struct gpx_data *)userData;\r
+\r
+       if (current_main_element!=0)\r
+       {\r
+               printf("unexpected <trk> element\n");\r
+               debug_pause();\r
+               exit(1);\r
+       }\r
+       current_main_element=GPX_ELEM_TYPE_TRK;\r
+\r
+       dat->trk_list=(struct gpxtrk **)xrealloc(dat->trk_list, (dat->trk_list_count+1)*sizeof(struct gpxtrk *));\r
+       dat->trk_list[dat->trk_list_count]=gpxtrk_new();\r
+       dat->trk_list_count++;\r
+}\r
+\r
+void endtrk(void *userData, const char *name)\r
+{\r
+//     struct gpx_data * dat = (struct gpx_data *)userData;\r
+\r
+       if (current_main_element!=GPX_ELEM_TYPE_TRK)\r
+       {\r
+               printf("unexpected </trk> element\n");\r
+               debug_pause();\r
+               exit(1);\r
+       }\r
+       current_main_element=0;\r
+\r
+//     printf("read end of track%d, with %d points\n", \r
+//                     dat->trk_list_count,\r
+//                     dat->trk_list[dat->trk_list_count-1]->trkpt_list_count); \r
+}\r
+\r
+// just eat <trkseg>: we join all track segments as a single track\r
+\r
+void starttrkseg(void *userData, const char *name, const char **atts)\r
+{\r
+       if (current_main_element!=GPX_ELEM_TYPE_TRK)\r
+       {\r
+               printf("unexpected <trkseg> element\n");\r
+               debug_pause();\r
+               exit(1);\r
+       }\r
+       current_main_element=GPX_ELEM_TYPE_TRKSEG;\r
+}\r
+\r
+void endtrkseg(void *userData, const char *name)\r
+{\r
+       if (current_main_element!=GPX_ELEM_TYPE_TRKSEG)\r
+       {\r
+               printf("unexpected </trkseq> element\n");\r
+               debug_pause();\r
+               exit(1);\r
+       }\r
+       current_main_element=GPX_ELEM_TYPE_TRK;\r
+}\r
+\r
+void starttrkpt(void *userData, const char *name, const char **atts)\r
+{\r
+       struct gpx_data * dat = (struct gpx_data *)userData;\r
+       struct gpxtrk * thistrk = dat->trk_list[dat->trk_list_count-1];\r
+\r
+       if (current_main_element!=GPX_ELEM_TYPE_TRKSEG)\r
+       {\r
+               printf("unexpected <trkpt> element\n");\r
+               debug_pause();\r
+               exit(1);\r
+       }\r
+       current_main_element=GPX_ELEM_TYPE_TRKPT;\r
+\r
+       thistrk->trkpt_list=(struct gpxpt **)xrealloc(thistrk->trkpt_list, \r
+                                                                                               (thistrk->trkpt_list_count+1)*sizeof(struct gpxpt *));\r
+       thistrk->trkpt_list[thistrk->trkpt_list_count]=gpxpt_new();\r
+       sscanf(get_att("lat", atts), "%lf", &(thistrk->trkpt_list[thistrk->trkpt_list_count]->lat));\r
+       sscanf(get_att("lon", atts), "%lf", &(thistrk->trkpt_list[thistrk->trkpt_list_count]->lon));\r
+       thistrk->trkpt_list_count++;\r
+}\r
+\r
+void endtrkpt(void *userData, const char *name)\r
+{\r
+       if (current_main_element!=GPX_ELEM_TYPE_TRKPT)\r
+       {\r
+               printf("unexpected </trkpt> element\n");\r
+               debug_pause();\r
+               exit(1);\r
+       }\r
+       current_main_element=GPX_ELEM_TYPE_TRKSEG;\r
+}\r
+\r
+void startname(void *userData, const char *name, const char **atts)\r
+{\r
+}\r
+\r
+void endname(void *userData, const char *name)\r
+{\r
+       struct gpx_data * dat = (struct gpx_data *)userData;\r
+       struct gpxrte* thisrte;\r
+//     struct gpxtrk* thistrk;\r
+       char* nameval = xrealloc(cdata, (cdata_length+1)*sizeof(XML_Char));\r
+       nameval[cdata_length]=0;\r
+       cdata=NULL;\r
+       cdata_length=0;\r
+       str2ascii(nameval);\r
+       switch (current_main_element)\r
+       {\r
+       case GPX_ELEM_TYPE_WPT:\r
+               dat->wpt_list[dat->wpt_list_count-1]->name=nameval;\r
+               break;\r
+       case GPX_ELEM_TYPE_RTE:\r
+               dat->rte_list[dat->rte_list_count-1]->name=nameval;\r
+               break;\r
+       case GPX_ELEM_TYPE_RTEPT:\r
+               thisrte = dat->rte_list[dat->rte_list_count-1];\r
+               thisrte->rtept_list[thisrte->rtept_list_count-1]->name=nameval;\r
+               break;\r
+       case GPX_ELEM_TYPE_TRK:\r
+//             thistrk = dat->trk_list[dat->trk_list_count-1];\r
+//             thistrk->trkpt_list[thistrk->trkpt_list_count-1]->name=nameval;\r
+               //break;\r
+       case GPX_ELEM_TYPE_TRKSEG:\r
+               //break;\r
+       case GPX_ELEM_TYPE_TRKPT:\r
+       default:\r
+               xfree(nameval);\r
+               break;\r
+       }\r
+}\r
+\r
+void startdesc(void *userData, const char *name, const char **atts)\r
+{\r
+}\r
+\r
+void enddesc(void *userData, const char *name)\r
+{\r
+       struct gpx_data * dat = (struct gpx_data *)userData;\r
+//     struct gpxrte* thisrte;\r
+//     struct gpxtrk* thistrk;\r
+       char* desc = xrealloc(cdata, cdata_length+1);\r
+       desc[cdata_length]=0;\r
+       cdata=NULL;\r
+       cdata_length=0;\r
+       str2ascii(desc);\r
+       switch (current_main_element)\r
+       {\r
+       case GPX_ELEM_TYPE_WPT:\r
+               str2ascii(desc);\r
+               dat->wpt_list[dat->wpt_list_count-1]->desc=desc;\r
+               break;\r
+       case GPX_ELEM_TYPE_RTE:\r
+//             dat->rte_list[dat->rte_list_count-1]->desc=desc;\r
+//             break;\r
+       case GPX_ELEM_TYPE_RTEPT:\r
+//             thisrte = dat->rte_list[dat->rte_list_count-1];\r
+//             thisrte->rtept_list[thisrte->rtept_list_count-1]->desc=desc;\r
+//             break;\r
+       case GPX_ELEM_TYPE_TRK:\r
+//             thistrk = dat->trk_list[dat->trk_list_count-1];\r
+//             thistrk->trkpt_list[thistrk->trkpt_list_count-1]->desc=desc;\r
+//             break;\r
+       case GPX_ELEM_TYPE_TRKSEG:\r
+//             break;\r
+       case GPX_ELEM_TYPE_TRKPT:\r
+       default:\r
+               xfree(desc);\r
+               break;\r
+       }\r
+}\r
+\r
+void startsrc(void *userData, const char *name, const char **atts)\r
+{\r
+}\r
+\r
+void endsrc(void *userData, const char *name)\r
+{\r
+}\r
+\r
+#define GPX_NUM_ELEM_HANDLERS 10\r
+\r
+gpx_elm_start_handler gpx_start_elm_handler[] = \r
+{\r
+       &startunkn,\r
+       &startwpt,\r
+       &startrte,\r
+       &startrtept,\r
+       &starttrk,\r
+       &starttrkseg,\r
+       &starttrkpt,\r
+       &startname,\r
+       &startdesc,\r
+       &startsrc\r
+};\r
+\r
+gpx_elm_end_handler gpx_end_elm_handler[] = \r
+{\r
+       &endunkn,\r
+       &endwpt,\r
+       &endrte,\r
+       &endrtept,\r
+       &endtrk,\r
+       &endtrkseg,\r
+       &endtrkpt,\r
+       &endname,\r
+       &enddesc,\r
+       &endsrc\r
+};\r
+\r
+\r
+int get_gpx_type_ndx(const char* type_name)\r
+{\r
+       int i;\r
+       for (i=1; i<GPX_NUM_ELEM_HANDLERS; i++)\r
+               if(strcmp(type_name, gpx_elem_name[i])==0)\r
+                       return i;\r
+       return 0;\r
+}\r
+\r
+static void XMLCALL\r
+startElement(void *userData, const char *name, const char **atts)\r
+{\r
+       int i = get_gpx_type_ndx(name);\r
+       gpx_start_elm_handler[i](userData, name, atts);\r
+\r
+       xfree(cdata);\r
+       cdata=NULL;\r
+       cdata_length=0;\r
+\r
+}\r
+\r
+static void XMLCALL\r
+endElement(void *userData, const char *name)\r
+{\r
+       int i;\r
+  i = get_gpx_type_ndx(name);\r
+  gpx_end_elm_handler[i](userData, name);\r
+}\r
+\r
+\r
+static void XMLCALL\r
+CharacterData(void *userData, const XML_Char *s, int len)\r
+{\r
+       // Remember s is not null-terminated!\r
+       // cdata is reset to NULL at the start of every element,\r
+       // which means we lose any cdata split by elements.\r
+       // Could be more clever and only copy cdata for types we want\r
+\r
+       cdata = xrealloc(cdata, (cdata_length+len)*sizeof(XML_Char));\r
+       memcpy(cdata+cdata_length, s, len);\r
+       cdata_length += len;\r
+}\r
+\r
+struct gpx_data * process_gpx_in_file(char* gpx_in_file_name)\r
+{\r
+\r
+       char buf[BUFSIZ];\r
+       XML_Parser parser = XML_ParserCreate(NULL);\r
+       int done;\r
+       FILE* gpx_in_file;\r
+\r
+       struct gpx_data * all_data = gpx_data_new();\r
+\r
+       all_data->data_source_name=(char*)xmalloc(strlen(gpx_in_file_name)+1);\r
+       strcpy(all_data->data_source_name, gpx_in_file_name);\r
+\r
+       XML_SetUserData(parser, all_data);\r
+       XML_SetElementHandler(parser, startElement, endElement);\r
+       XML_SetCharacterDataHandler(parser, CharacterData);\r
+\r
+       if(gpx_in_file_name==NULL)\r
+       {\r
+               fprintf(stderr, "Unexpected null filename for gpx_in_file_name\n");\r
+               debug_pause();\r
+               exit(1);\r
+       }\r
+       else\r
+       {\r
+               printf("Importing data from %s\n", gpx_in_file_name);\r
+               gpx_in_file = fopen(gpx_in_file_name, "r");\r
+       }\r
\r
+       if(gpx_in_file==NULL)\r
+       {\r
+               fprintf(stderr, "Unable to open GPX file %s\n", gpx_in_file_name);\r
+               debug_pause();\r
+               exit(1);\r
+       }\r
+\r
+       do \r
+       {\r
+               size_t len = fread(buf, 1, sizeof(buf), gpx_in_file);\r
+               done = len < sizeof(buf);\r
+               if (XML_Parse(parser, buf, len, done) == XML_STATUS_ERROR) \r
+               {\r
+                       fprintf(stderr,\r
+                               "%s at line %d\n",\r
+                               XML_ErrorString(XML_GetErrorCode(parser)),\r
+                               XML_GetCurrentLineNumber(parser));\r
+                       return all_data;\r
+               }\r
+       } while (!done);\r
+       XML_ParserFree(parser);\r
+\r
+       if (opts.verbose_flag > 2)\r
+       {\r
+       }\r
+\r
+       xfree(cdata);\r
+\r
+       return all_data;\r
+}\r
diff --git a/st2gpx/src/readmpst.c b/st2gpx/src/readmpst.c
new file mode 100644 (file)
index 0000000..3a75d30
--- /dev/null
@@ -0,0 +1,400 @@
+/*\r
+       readmpst.c\r
+\r
+       Extract data from MS Streets & Trips .est and Autoroute .axe files in GPX format.\r
+\r
+    Copyright (C) 2003 James Sherring, james_sherring@yahoo.com\r
+\r
+    This program is free software; you can redistribute it and/or modify\r
+    it under the terms of the GNU General Public License as published by\r
+    the Free Software Foundation; either version 2 of the License, or\r
+    (at your option) any later version.\r
+\r
+    This program is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+\r
+    You should have received a copy of the GNU General Public License\r
+    along with this program; if not, write to the Free Software\r
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA\r
+\r
+\r
+       This app depends on istorage & istorage-make from Pabs (pabs3@zip.to)\r
+       and James Clark's Expat xml parser from http://www.libexpat.org/.\r
+\r
+*/\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+\r
+#include "st2gpx.h"\r
+#include "gpx.h"\r
+\r
+#define STATUS_BOF                                     1\r
+#define STATUS_EOF                                     2\r
+#define STATUS_FILE_HEADER                     3\r
+\r
+#define STATUS_WPT_LIST_HEADER         4\r
+#define STATUS_WPT_LIST_BODY           5\r
+\r
+#define STATUS_RTE_LIST_HEADER         6\r
+#define STATUS_RTE_ITEM                                7\r
+#define STATUS_RTE_PT_LIST_HEADER      8\r
+#define STATUS_RTE_PT_LIST_BODY                9\r
+\r
+#define STATUS_TRK_LIST_HEADER         10\r
+#define STATUS_TRK_ITEM                                11\r
+#define STATUS_TRK_PT_LIST_HEADER      12\r
+#define STATUS_TRK_PT_LIST_BODY                13\r
+\r
+#define MAX_FIELD_WIDTH 50\r
+// I have files with 1300 lines\r
+#define MAX_LINES 10000\r
+//#define MAX_LINES 200\r
+\r
+//#define MAX_FIELDS 20;\r
+//char* list_header_fieldnames[MAX_FIELDS];\r
+//char* list_header_values[MAX_FIELDS];\r
+//char* list_fieldnames[MAX_FIELDS];\r
+//char* list_values[MAX_FIELDS];\r
+\r
+const char* garmin_16_symbols[16]=\r
+{\r
+               "Waypoint",\r
+               "Residence",\r
+               "Gas Station",\r
+               "Car",\r
+               "Fishing Area",\r
+               "Boat Ramp",\r
+               "Marina",\r
+               "Shipwreck",\r
+               "Exit",\r
+               "Skull and Crossbones",\r
+               "Flag",\r
+               "Campground",\r
+               "Circle with X",\r
+               "Hunting Area",\r
+               "Medical Facility",\r
+               "TrackBack Point"\r
+};\r
+\r
+struct gpx_data * read_mpstext(char* mpstxt_file_name)\r
+{\r
+       char line_buf[1001];\r
+       FILE* mpstxt_file = fopen(mpstxt_file_name, "r");\r
+       //int byte_read;\r
+       int status=STATUS_FILE_HEADER;\r
+       int last_status=STATUS_BOF;\r
+       int this_blank=0;\r
+       int last_blank=0;\r
+       char * fgets_status;\r
+       int parsed_vars=0;\r
+\r
+       int loop_count=0;\r
+\r
+       // being lazy a lot of large variables\r
+       char f_Name[ MAX_FIELD_WIDTH ];\r
+       char f_Desc[ MAX_FIELD_WIDTH ];\r
+       char f_Type[ MAX_FIELD_WIDTH ];\r
+       char f_lat_dir;\r
+       double f_lat;\r
+       char f_lon_dir;\r
+       double f_lon;\r
+       char f_Altitude[ MAX_FIELD_WIDTH ];\r
+       char f_Depth[ MAX_FIELD_WIDTH ];\r
+       char f_Proximity[ MAX_FIELD_WIDTH ];\r
+       char f_DisplayMode[ MAX_FIELD_WIDTH ];\r
+       char f_Color[ MAX_FIELD_WIDTH ];\r
+       char f_Symbol[ MAX_FIELD_WIDTH ];\r
+       char f_Facility[ MAX_FIELD_WIDTH ];\r
+       char f_City[ MAX_FIELD_WIDTH ];\r
+       char f_State[ MAX_FIELD_WIDTH ];\r
+       char f_Country[ MAX_FIELD_WIDTH ];\r
+\r
+       char f_Length[ MAX_FIELD_WIDTH ];\r
+       char f_Course[ MAX_FIELD_WIDTH ];\r
+       char Waypoints[ MAX_FIELD_WIDTH ];\r
+\r
+       char f_WaypointName[ MAX_FIELD_WIDTH ];\r
+       char f_Distance[ MAX_FIELD_WIDTH ];\r
+       char f_LegLength[ MAX_FIELD_WIDTH ];\r
+\r
+       char f_StartTime[ MAX_FIELD_WIDTH ];\r
+       char f_ElapsedTime[ MAX_FIELD_WIDTH ];\r
+       char f_AverageSpeed[ MAX_FIELD_WIDTH ];\r
+       char f_DateTime[ MAX_FIELD_WIDTH ];\r
+       char f_LegTime[ MAX_FIELD_WIDTH ];\r
+       char f_LegSpeed[ MAX_FIELD_WIDTH ];\r
+       char f_LegCourse[ MAX_FIELD_WIDTH ];\r
+\r
+       struct gpx_data * dat = gpx_data_new();\r
+       struct gpxpt * this_gpxpt=NULL;\r
+       struct gpxpt * matching_wpt=NULL;\r
+       struct gpxrte * thisrte=NULL;\r
+\r
+       dat->data_source_name=(char*)xmalloc(strlen(mpstxt_file_name)+1);\r
+       strcpy(dat->data_source_name, mpstxt_file_name);\r
+\r
+       if (mpstxt_file==NULL)\r
+       {\r
+               printf("Error opening MapSource text file %s for input\n", mpstxt_file_name);\r
+               debug_pause();\r
+               exit(1);\r
+       }\r
+       else\r
+               printf("Reading MapSource text file %s\n", mpstxt_file_name);\r
+\r
+       while (status!=STATUS_EOF)\r
+       {\r
+               fgets_status = fgets((char*)line_buf, 1000, mpstxt_file);\r
+               if (fgets_status==NULL)\r
+                       status=STATUS_EOF;\r
+\r
+               //printf("read %d bytes in line: %s\n", bytes_read, line_buf);\r
+\r
+               if (strcmp(line_buf,"\n")==0)\r
+                       this_blank=1;\r
+               else\r
+                       this_blank=0;\r
+\r
+               switch(status)\r
+               {\r
+               case STATUS_FILE_HEADER:\r
+                       // Just eat all header lines until a this_blank line\r
+                       // We should verify this header\r
+\r
+                       // FIXME We need to check that Grid=Lat/Lon hddd.ddddd° \r
+                       // to be sure we can read the data\r
+                       if (this_blank)\r
+                               status=STATUS_WPT_LIST_HEADER;\r
+                       break;\r
+\r
+               case STATUS_WPT_LIST_HEADER:\r
+                       // check type & set proper status\r
+                       if (this_blank)\r
+                               status=STATUS_WPT_LIST_BODY;\r
+                       break;\r
+\r
+               case STATUS_WPT_LIST_BODY:\r
+                       if (this_blank)\r
+                       {\r
+                               status=STATUS_RTE_LIST_HEADER;\r
+                       }\r
+                       else\r
+                       {\r
+                               parsed_vars=sscanf(line_buf, "Waypoint\t%[^\t]\t%[^\t]\t%[^\t]\t%c%lf %c%lf\t%[^\t]\t%[^\t]\t%[^\t]\t%[^\t]\t%[^\t]\t%[^\t]\t%[^\t]\t%[^\t]\t%[^\t]\t%[^\t]",\r
+                                       &f_Name, &f_Desc, &f_Type,  &f_lat_dir, &f_lat, &f_lon_dir, &f_lon, &f_Altitude,\r
+                                       &f_Depth, &f_Proximity, &f_DisplayMode, &f_Color, &f_Symbol, &f_Facility,\r
+                                       &f_City, &f_State, &f_Country);\r
+                               if (parsed_vars<4)\r
+                               {\r
+                                       printf("Error parsing line %d as a waypoint. Need at least 4 vars, only got %d\n", \r
+                                                       loop_count+1, parsed_vars);\r
+                                       printf("Problem line is: %s\n", line_buf);\r
+                               }\r
+                               else\r
+                               {\r
+                                       dat->wpt_list=(struct gpxpt **)xrealloc(dat->wpt_list, (dat->wpt_list_count+1)*sizeof(struct gpxpt *));\r
+                                       this_gpxpt = dat->wpt_list[dat->wpt_list_count] = gpxpt_new();\r
+                                       \r
+                                       if (f_lat_dir=='S')\r
+                                               f_lat=-f_lat;\r
+                                       else if(f_lat_dir!='N')\r
+                                               printf("Error parsing line %d as a waypoint. '%c' when expecting 'N' or 'S' for latitdue.\n", f_lat_dir);\r
+\r
+                                       if (f_lon_dir=='W')\r
+                                               f_lon=-f_lon;\r
+                                       else if(f_lon_dir!='E')\r
+                                               printf("Error parsing line %d as a waypoint. '%c' when expecting 'E' or 'W' for longitude.\n", f_lat_dir);\r
+                                       \r
+                                       this_gpxpt->lat = f_lat;\r
+                                       this_gpxpt->lon = f_lon;\r
+                                       this_gpxpt->name=xmalloc(strlen(f_Name)+1);\r
+                                       strcpy(this_gpxpt->name, f_Name);\r
+                                       str2ascii(this_gpxpt->name);\r
+                                       this_gpxpt->desc=xmalloc(strlen(f_Desc)+1);\r
+                                       strcpy(this_gpxpt->desc, f_Desc);\r
+                                       str2ascii(this_gpxpt->desc);\r
+                                       dat->wpt_list_count++;\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case STATUS_RTE_LIST_HEADER:\r
+                       // check type & set proper status\r
+                       if (this_blank && !last_blank)\r
+                               status=STATUS_RTE_ITEM;\r
+                       break;\r
+\r
+               case STATUS_RTE_ITEM:\r
+                       if (this_blank)\r
+                       {\r
+                               if (last_blank)\r
+                                       status=STATUS_TRK_LIST_HEADER;\r
+                               else\r
+                                       status=STATUS_RTE_PT_LIST_HEADER;\r
+                       }\r
+                       else\r
+                       {\r
+                               parsed_vars=sscanf(line_buf, "Route\t%[^\t]\t%[^\t]\t%[^\t]\t%[^\t]",\r
+                                               &f_Name, &f_Length, &f_Course, &Waypoints);\r
+                               if (parsed_vars<1)\r
+                               {\r
+                                       printf("Error parsing line %d as a route. Need at least 1 var, only got %d\n", \r
+                                                       loop_count+1, parsed_vars);\r
+                                       printf("Problem line is: %s\n", line_buf);\r
+                               }\r
+                               else\r
+                               {\r
+                                       dat->rte_list=(struct gpxrte **)xrealloc(dat->rte_list, (dat->rte_list_count+1)*sizeof(struct gpxrte *));\r
+                                       dat->rte_list[dat->rte_list_count]=gpxrte_new();\r
+                                       dat->rte_list[dat->rte_list_count]->name = xmalloc(strlen(f_Name)+1);\r
+                                       str2ascii(f_Name);\r
+                                       strcpy(dat->rte_list[dat->rte_list_count]->name, f_Name);\r
+                                       dat->rte_list_count++;\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case STATUS_RTE_PT_LIST_HEADER:\r
+                       if (this_blank)\r
+                               status=STATUS_RTE_PT_LIST_BODY;\r
+                       break;\r
+\r
+               case STATUS_RTE_PT_LIST_BODY:\r
+                       if (this_blank)\r
+                               //loop back to another new route\r
+                               status=STATUS_RTE_ITEM;\r
+                       else\r
+                       {\r
+                               parsed_vars=sscanf(line_buf, "Route Waypoint\t%[^\t]\t%[^\t]\t%[^\t]\t%[^\t]",\r
+                                       &f_WaypointName, &f_Distance, &f_LegLength, &f_Course);\r
+                               if (parsed_vars<1)\r
+                               {\r
+                                       printf("Error parsing line %d as a routepoint. Need at least 1 var, only got %d\n", \r
+                                                       loop_count+1, parsed_vars);\r
+                                       printf("Problem line is: %s\n", line_buf);\r
+                               }\r
+                               else\r
+                               {\r
+                                       matching_wpt=find_matching_wpt(dat, f_WaypointName);\r
+                                       if (matching_wpt == NULL)\r
+                                       {\r
+                                               printf("Ignoring routepoint %s because I cant match it to any waypoints\n",\r
+                                                               f_WaypointName);\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               thisrte = dat->rte_list[dat->rte_list_count-1];\r
+                                               thisrte->rtept_list=(struct gpxpt **)xrealloc(thisrte->rtept_list, \r
+                                                                                       (thisrte->rtept_list_count+1)*sizeof(struct gpxpt *));\r
+                                               this_gpxpt = thisrte->rtept_list[thisrte->rtept_list_count] = gpxpt_copy(matching_wpt);\r
+                                               thisrte->rtept_list_count++;\r
+                                       }\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case STATUS_TRK_LIST_HEADER:\r
+                       // check type & set proper status\r
+                       if (this_blank && !last_blank)\r
+                               status=STATUS_TRK_ITEM;\r
+                       break;\r
+\r
+               case STATUS_TRK_ITEM:\r
+                       if (this_blank)\r
+                       {\r
+                               if (last_blank)\r
+                                       status=STATUS_EOF;\r
+                               else\r
+                                       status=STATUS_TRK_PT_LIST_HEADER;\r
+                       }\r
+                       else\r
+                       {\r
+                               parsed_vars=sscanf(line_buf, "Track\t%[^\t]\t%[^\t]\t%[^\t]\t%[^\t]\t%[^\t]",\r
+                                       &f_Name, &f_StartTime, &f_ElapsedTime, &f_Length, &f_AverageSpeed);\r
+                               if (parsed_vars<1)\r
+                               {\r
+                                       printf("Error parsing line %d as a Track. Need at least 1 var, only got %d\n", \r
+                                                       loop_count+1, parsed_vars);\r
+                                       printf("Problem line is: %s\n", line_buf);\r
+                               }\r
+                               else\r
+                               {\r
+                                       dat->trk_list=(struct gpxtrk **)xrealloc(dat->trk_list, \r
+                                                                               (dat->trk_list_count+1)*sizeof(struct gpxtrk *));\r
+                                       dat->trk_list[dat->trk_list_count]=gpxtrk_new();\r
+                                       //dat->trk_list[dat->trk_list_count]->name = (char*)malloc(strlen(f_Name)+1);\r
+                                       //strcpy(dat->trk_list[dat->trk_list_count]->name, f_Name);\r
+                                       dat->trk_list_count++;\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case STATUS_TRK_PT_LIST_HEADER:\r
+                       if (this_blank)\r
+                               status=STATUS_TRK_PT_LIST_BODY;\r
+                       break;\r
+\r
+               case STATUS_TRK_PT_LIST_BODY:\r
+                       if (this_blank)\r
+                               // loop back for another new track\r
+                               status=STATUS_TRK_ITEM;\r
+                       else\r
+                       {\r
+                               parsed_vars=sscanf(line_buf, "Trackpoint\t%c%lf %c%lf\t%[^\t]\t%[^\t]\t%[^\t]\t%[^\t]\t%[^\t]\t%[^\t]",\r
+                                       &f_lat_dir, &f_lat, &f_lon_dir, &f_lon, &f_DateTime, &f_Altitude,\r
+                                       &f_Depth, &f_LegLength, &f_LegTime, &f_LegSpeed, &f_LegCourse);\r
+                               if (parsed_vars<4)\r
+                               {\r
+                                       printf("Error parsing line %d as a track-point. Need at least 4 vars, only got %d\n", \r
+                                                       loop_count+1, parsed_vars);\r
+                                       printf("Problem line is: %s\n", line_buf);\r
+                               }\r
+                               else\r
+                               {\r
+                                       struct gpxtrk * thistrk = dat->trk_list[dat->trk_list_count-1];\r
+                                       thistrk->trkpt_list=(struct gpxpt **)xrealloc(thistrk->trkpt_list, \r
+                                                                                       (thistrk->trkpt_list_count+1)*sizeof(struct gpxpt *));\r
+                                       thistrk->trkpt_list[thistrk->trkpt_list_count]=gpxpt_new();\r
+\r
+                                       if (f_lat_dir=='S')\r
+                                               f_lat=-f_lat;\r
+                                       else if(f_lat_dir!='N')\r
+                                               printf("Error parsing line %d as a waypoint. '%c' when expecting 'N' or 'S' for latitdue.\n", f_lat_dir);\r
+\r
+                                       if (f_lon_dir=='W')\r
+                                               f_lon=-f_lon;\r
+                                       else if(f_lon_dir!='E')\r
+                                               printf("Error parsing line %d as a waypoint. '%c' when expecting 'E' or 'W' for longitude.\n", f_lat_dir);\r
+\r
+                                       thistrk->trkpt_list[thistrk->trkpt_list_count]->lat=f_lat;\r
+                                       thistrk->trkpt_list[thistrk->trkpt_list_count]->lon=f_lon;\r
+                                       thistrk->trkpt_list_count++;\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               default:\r
+                       {;\r
+                       }\r
+               }\r
+\r
+               last_status=status;\r
+               last_blank=this_blank;\r
+\r
+               loop_count++;\r
+               if (loop_count>MAX_LINES)\r
+               {\r
+                       printf("Read %d input lines, which seems rather high\n", loop_count);\r
+                       break;\r
+               }\r
+\r
+       }\r
+       \r
+       if(opts.verbose_flag>4)\r
+               print_gpx_data(dat);\r
+\r
+       return dat;\r
+}\r
diff --git a/st2gpx/src/st2gpx license.txt b/st2gpx/src/st2gpx license.txt
new file mode 100644 (file)
index 0000000..5068e43
--- /dev/null
@@ -0,0 +1,23 @@
+st2gpx\r
+\r
+Extract data from MS Streets & Trips .est and Autoroute .axe files in GPX format.\r
+\r
+Copyright (C) 2003 James Sherring, james_sherring@yahoo.com\r
+\r
+    This program is free software; you can redistribute it and/or modify\r
+    it under the terms of the GNU General Public License as published by\r
+    the Free Software Foundation; either version 2 of the License, or\r
+    (at your option) any later version.\r
+\r
+    This program is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+\r
+    You should have received a copy of the GNU General Public License\r
+    along with this program; if not, write to the Free Software\r
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA\r
+\r
+\r
+st2gpx depends on istorage & istorage-make from Pabs (pabs3@zip.to)\r
+and James Clark's Expat xml parser from http://www.libexpat.org/.\r
index 8b5c17a7526ac0d98a7139c85d0a0381759951c5..66ff4d1e9a0c009ceb1da15ed8a2010522a02ccc 100644 (file)
@@ -1,5 +1,5 @@
 /*\r
-       st2gpxmain.c\r
+       st2gpx.c\r
 \r
        Extract data from MS Streets & Trips .est and Autoroute .axe files in GPX format.\r
 \r
     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA\r
 \r
 \r
-History:\r
+       This app depends on istorage & istorage-make from Pabs (pabs3@zip.to)\r
+       and James Clark's Expat xml parser from http://www.libexpat.org/.\r
 \r
-21-10-2003     annotations stream dump\r
-27-10-2003     journey & pushpins using VB module\r
- 8-11-2003     match journey route-points to pushpins,\r
-                       integrate parts into singel C/C++ exe (except istorage)\r
- 9-11-2003  fixed invalid gpx\r
-\r
-To do:\r
-       Get lat & lon for journey route points not matched to pushpins\r
-       Get point info for non-line annotations, e.g. text boxes.\r
-       Import functionality\r
-       Implement using platform independant libraries.\r
-\r
-bugs:\r
-       unable to delete UserData file after accessing with ADO.\r
 */\r
 \r
 #include <stdio.h>\r
 #include <stdlib.h>\r
-#include <malloc.h>\r
 #include <memory.h>\r
 #include <math.h>\r
 #include <string.h>\r
 \r
+#include <malloc.h>\r
+#include <crtdbg.h>\r
+\r
+\r
 // #include <getopt.h>\r
 #include "getopt.h"\r
+#include "gpx.h"\r
+#include "st2gpx.h"\r
+#include "annotations.h"\r
+#include "journey.h"\r
+#include "properties.h"\r
+#include "contents.h"\r
+#include "ppinutil.h"\r
 #include "pushpins.h"\r
 \r
-#ifndef M_PI\r
-#define M_PI 3.1415926535\r
-#endif\r
-\r
-#define JOUR_FILE_HEAD_LEN 32\r
-#define JOUR_FILE_TAIL_LEN 430\r
-// + text1 +2*text2\r
-#define JOUR_WPTREC_LEN 121\r
-\r
-#define JOUR_FILEOS_NUMREC 16\r
-\r
-#define JOURWPT_REC_HEAD_LEN 41\r
-\r
-#define JOURWPT_RECOS_WPTNUM 0\r
-#define JOURWPT_RECOS_STR1LEN 40\r
-#define JOURWPT_RECOS_STR1 41\r
-// + val(JOURWPT_RECOS_STR1LEN)\r
-#define JOURWPT_RECOS_STR2LEN 44\r
-#define JOURWPT_RECOS_STR2 45\r
-\r
-#define ANNOT_FILE_HEAD_LEN 12\r
-// This needs to be long enough to get enough params to decide which record,\r
-// but no biger than the shortest record\r
-#define ANNOT_REC_HEAD_LEN 57 //19\r
-\r
-#define ANNOT_TYPE_LINE                0\r
-#define ANNOT_TYPE_OVAL                1\r
-#define ANNOT_TYPE_TEXT                2\r
-#define ANNOT_TYPE_CIRCLE      3\r
-\r
-#define REC_CLOSE_LEN 0\r
-// offsets for parameters in annotation recods\r
-#define ANNOT_RECOS_TYPE       0\r
-#define ANNOT_RECOS_ANUM       4\r
-#define ANNOT_RECOS_TEXTLEN    20\r
-#define ANNOT_RECOS_TEXT       24\r
-#define ANNOT_RECOS_LINENUMPOINTS 53\r
-#define ANNOT_RECOS_LINEJOINFLAG 48\r
-#define ANNOT_RECOS_XSCALE     48\r
-#define ANNOT_RECOS_YSCALE     52\r
-\r
-#define GPX_HEADER1 "<?xml version=\"1.0\" standalone=\"yes\"?>\n<gpx version=\"1.0\" \n  xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n  xmlns=\"http://www.topografix.com/GPX/1/0\"\n  xsi:schemaLocation=\"http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd\"\n "\r
-#define GPX_HEADER2 " creator=\"st2gpx-james_sherring@yahoo.com\">\n"\r
-#define GPX_THIS_PROGRAM "st2gpx from james_sherring@yahoo.com"\r
-#define GPX_FOOTER "</gpx>"\r
-\r
-#define GPX_WPT 0\r
-#define GPX_RTEPT 1\r
-#define GPX_TRKPT 2\r
-\r
-/*\r
-typedef struct annotationbuf\r
-{\r
-       int annot_num;\r
-       int flags;              // bit fields in first byte\r
-       int unkn1;              // normally 0\r
-       int unkn2;              // ? seems to have byte fields\r
-       int text_len;\r
-       // + 2*text_len bytes of text here\r
-       int fill_color; // seems to have byte fields. First byte is fill, other bytes are strange\r
-       int line_color;\r
-       int line_thickness; // 20 times the point-size\r
-       int arrow_type;         // 00=none, 01=left, 02=right, 03=both\r
-       int unkn3;\r
-       int joinflag;           // 0 line does not join, 1, joins. Not sure what large balues for non-lines mean - xscale?\r
-       char unkn4;                     // y-scale?\r
-       int num_points;         // different meaning for non-lines\r
-} structannotationbuf;\r
-*/\r
-\r
-typedef struct jourwpt_rec\r
-{\r
-       int jour_num;\r
-       int text1_length;\r
-       char* text1;\r
-       int text2_length;\r
-       char* text2;\r
-       long UdId;\r
-       struct pushpin* pushpin;\r
-       int buf_length;\r
-       char* buf;\r
-} tag_jour_rec;\r
-\r
-typedef struct gpx_point\r
-{\r
-       float lat;\r
-       float lon;\r
-       float height;\r
-} tag_gpx_point;\r
-\r
-typedef char* annot_file_header;\r
-typedef char* annot_rec_header;\r
-typedef char* annot_buf;\r
-\r
-typedef struct annot_rec\r
-{\r
-       int type;\r
-       int length;\r
-       char* buf;\r
-       int annot_num;\r
-       int text_length;\r
-       char* text;\r
-       int line_points;\r
-} tag_annot_rec;\r
-\r
-struct point {\r
-       double lon;\r
-       double lat;\r
-} tag_point;\r
-\r
-struct ms_point {\r
-       long grid;\r
-       long precision;\r
-} tag_ms_point;\r
-\r
-\r
-// Also need to include variable text length + line-points with these\r
-int annot_rec_len[4]={57, 868, 124, 868};\r
-int annot_head_len[4]={57, 48, 48, 48};\r
-char* annot_type_name[4]={"Line", "Oval", "Textbox", "Circle"};\r
-static char* gpxptypelabel[] = {"wpt", "rtept", "trkpt"};\r
-\r
-// constants for converting from MS Grid & Precision to latitude and longitude\r
-double magic1 = 182.044444444444;\r
-double magic2 = 0x10000;\r
-\r
-// Args set by getopt etc\r
-\r
-FILE* ppin_file=NULL;\r
-FILE* jour_file=NULL;\r
-FILE* annot_file=NULL;\r
-FILE* gpx_file=NULL;\r
-char* source_file_name=NULL;\r
-\r
-/* Flag set by --verbose. */\r
-// 0 - only errors\r
-// 1 also the structured data output, e.g. line point info\r
-// 2 also record types & parameters\r
-// 3 also detailed summary info\r
-// 4 also detailed analysis of headers & record params\r
-// 5 also dump buffers\r
-// 6 lots of debug info\r
-static int verbose_flag = 2;\r
-static int explore_flag = 0;\r
-// force line-type annotations to be exported as GPX routes instead of tracks\r
-static int use_gpx_route = 0;\r
-\r
-// std_anotfile_header[8,9] are variable (number of annotations)\r
-char std_annotfile_header[ANNOT_FILE_HEAD_LEN] =\r
-                       {0x34, 0x12, 0x00, 0x2d, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00};\r
+struct st2gpx_options opts;\r
 \r
 void * xmalloc(size_t size)\r
 {\r
-       void *obj = malloc(size);\r
-       if (!obj)\r
+       void *obj;\r
+       if (size<0)\r
        {\r
-               fprintf(stderr, "Unable to allocate %d bytes of memory.\n", size);\r
+               fprintf(stderr, "**** Error: trying to malloc %d bytes ****/n");\r
+               debug_pause();\r
+               exit(-1);\r
        }\r
-       return obj;\r
-}\r
-\r
-void * xrealloc(void* ptr, size_t size)\r
-{\r
-       void *obj = realloc(ptr, size);\r
+//#ifdef   _DEBUG\r
+//     obj = _malloc_dbg(size, _NORMAL_BLOCK, __FILE__, __LINE__ );\r
+//#else\r
+       obj = malloc(size);\r
+//#endif\r
        if (!obj)\r
        {\r
-               fprintf(stderr, "Unable to (re)allocate %d bytes of memory.\n", size);\r
+               fprintf(stderr, "Unable to allocate %d bytes of memory.\n", size);\r
+               debug_pause();\r
+               exit(-1);\r
        }\r
-       return obj;\r
-}\r
 \r
-int fixhex(char c)\r
-{\r
-// gcc (version?) does not print single byte hex vaues properly\r
-// eg 0xe3 prints as 0xFFFFFFE3\r
-// this is only a problem for values above 0x80\r
-// Or maybe that is the proper handling of unsigned?\r
-// Aaaahhh. I should use %u for printing unsigned... but the hex problem is still there\r
-       if(c & 0x80)\r
-       {\r
-               return ((int)c-0xFFFFFF00);\r
-       } else\r
-               return c;\r
-}\r
+#ifdef _DEBUG\r
+#ifdef MEMTRACE\r
+       printf("Malloc'd %d bytes at %lx\n", size, obj);\r
+#endif\r
+#endif\r
 \r
-void printbuf(char* buf, int len)\r
-{\r
-//     unsigned i;\r
-       int i;\r
-       printf("     0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F\n");\r
-       printf("    -----------------------------------------------");\r
-       for(i=0; i<len; i++)\r
-       {\r
-               if (((i+1) & 0x0f) == 0x1)\r
-                       printf("\n%2x| ",i/16);\r
-               printf("%2x ",fixhex(buf[i]));\r
-       }\r
-       printf("\n\n");\r
+       return obj;\r
 }\r
 \r
-void printbufwide(char* buf, int len)\r
+void * xrealloc(void* ptr, size_t size)\r
 {\r
-       int i;\r
-       for(i=0; i<len; i++)\r
+       void *obj;\r
+       if (size<0)\r
        {\r
-               printf("%2x ",fixhex(buf[i]));\r
+               fprintf(stderr, "**** Error: trying to malloc %d bytes ****/n");\r
+               debug_pause();\r
+               exit(-1);\r
        }\r
-       printf("\n\n");\r
-}\r
 \r
-void printbufhigh(char* buf, int len)\r
-{\r
-       int i;\r
-       for(i=0; i<len; i++)\r
-       {\r
-               printf("%02x %02x\n", i, fixhex(buf[i]));\r
-       }\r
-       printf("\n\n");\r
-}\r
+#ifdef _DEBUG\r
+#ifdef MEMTRACE\r
+       printf("reallocing from %lx\n", ptr);\r
+#endif\r
+#endif\r
 \r
-void printbufasfloat(char* buf, int len)\r
-{\r
-//     unsigned i;\r
-       int i;\r
-//     printf("     0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F\n");\r
-//     printf("    -----------------------------------------------");\r
-       for(i=0; i<len-3; i++)\r
+//#ifdef   _DEBUG\r
+//     obj = _realloc_dbg(ptr, size, _NORMAL_BLOCK, __FILE__, __LINE__ );\r
+//#else\r
+       obj = realloc(ptr, size);\r
+//#endif\r
+       if (!obj)\r
        {\r
-               if (((i+1) & 0x03) == 0x1)\r
-                       printf("\n%2x| ",i);\r
-               printf("%f  ", *(float*)(buf+i));\r
-               fflush(stdout);\r
+               fprintf(stderr, "Unable to (re)allocate %d bytes of memory.\n", size);\r
+               debug_pause();\r
+               exit(-1);\r
        }\r
-       printf("\n\n");\r
-}\r
 \r
-void printfloatbuf(float* fbuf, int len)\r
-{\r
-//     unsigned i;\r
-       int i;\r
-//     printf("     0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F\n");\r
-//     printf("    -----------------------------------------------");\r
-       for(i=0; i<len; i++)\r
-       {\r
-               if (((i+1) & 0x03) == 0x1)\r
-                       printf("\n%2x| ",4*i);\r
-               printf("%f  ", fbuf[i]);\r
-               fflush(stdout);\r
-       }\r
-       printf("\n\n");\r
-}\r
+#ifdef _DEBUG\r
+#ifdef MEMTRACE\r
+       printf("realloc'd %d bytes at %lx\n", size, obj);\r
+#endif\r
+#endif\r
 \r
-struct gpx_point gpx_get_point(char* buf)\r
-{\r
-// need to be sure this is done with double precision\r
-       struct gpx_point pt;\r
-       double x;\r
-       double y;\r
-       double z;\r
-\r
-       x= *(float *)(buf);\r
-       y= *(float *)(buf + 4);\r
-       z= *(float *)(buf + 8);\r
-\r
-       //printf("gpx_get_point x=%f y=%f z=%f\n",x,y,z);\r
-       pt.lat =  atan2(z,sqrt(pow(x,2)+ pow(y,2)))*180/M_PI;\r
-       pt.lon =  atan2(y,x)*180/M_PI;\r
-       // 6378137 is earths equatorial radius in meters\r
-       pt.height = (sqrt(pow(x,2)+ pow(y,2)+ pow(z,2))-1)*6378137;\r
-       return pt;\r
+       return obj;\r
 }\r
 \r
-void printpoints(char* buf, int numpts)\r
+void xfree(void * obj)\r
 {\r
-       int i;\r
-//     int j;\r
-       struct gpx_point pt;\r
-       printf("Latitude  Longitude Height");\r
-       printf("\n");\r
-       printf("--------------------------\n");\r
-       for(i=0; i<numpts; i++)\r
-       {\r
-               pt = gpx_get_point(buf + 12*i);\r
-               printf("%f %f %f \n",pt.lat, pt.lon, pt.height);\r
-       }\r
-       printf("\n\n");\r
-}\r
+//#ifdef   _DEBUG\r
+//     _free_dbg(obj, _NORMAL_BLOCK);\r
+//#else\r
 \r
-void printpointsbuf(char* buf, int len)\r
-{\r
-//     unsigned i;\r
-//     unsigned j;\r
-       int i;\r
-       int j;\r
-       printf("     0  1  2  3  4  5  6  7  8  9  A  B\n");\r
-       printf("    -----------------------------------");\r
-       for(i=0; i<len; i++)\r
-       {\r
-               printf("\n%2x| ",i);\r
-       //      printf("\n");\r
-               for (j=0; j<12; j++)\r
-               {\r
-                       printf("%2x ",fixhex(buf[12*i+j]));\r
-                       fflush(stdout);\r
-               }\r
-       }\r
-       printf("\n\n");\r
-}\r
+#ifdef _DEBUG\r
+#ifdef MEMTRACE\r
+       printf("freeing mem at %lx\n", obj);\r
+#endif\r
+#endif\r
 \r
-void printbufaspoints(char* buf, int buflen)\r
-{\r
-       int i;\r
-//     int j;\r
-       struct gpx_point pt;\r
-       printf("Latitude  Longitude Height");\r
-       printf("\n");\r
-       printf("--------------------------\n");\r
-       for(i=0; i<buflen-11; i++)\r
-       {\r
-               pt = gpx_get_point(buf + 12*i);\r
-               printf("%#02x %f N %f E %f m \n", i, pt.lat, pt.lon, pt.height);\r
-               fflush(stdout);\r
-       }\r
-       printf("\n\n");\r
+       free(obj);\r
+// #endif\r
 }\r
 \r
-void printnzbuf(char* buf, int len)\r
+char * str2ascii(char* str)\r
 {\r
-// print non-zero values in the buffer\r
-//     unsigned i;\r
        int i;\r
+       int len=strlen(str);\r
+       unsigned char * ustr = (unsigned char*)str;\r
        for(i=0; i<len; i++)\r
-       {\r
-//             if (buf[i] != 0) printf("Buf[%x]=%2x ",fixhex(i), fixhex(buf[i]));\r
-               if (buf[i] != 0) printf("Buf[%x]=%2x ",i, fixhex(buf[i]));\r
-       }\r
-       printf("\n");\r
-}\r
-\r
-void printnzhead(struct annot_rec rec)\r
-{\r
-       printnzbuf(rec.buf, annot_head_len[rec.type]);\r
-}\r
-\r
-struct point ms2latlong(struct ms_point msp) {\r
-\r
-// grid and precision are the high and low words obtained by interleaving the bits\r
-// of latitude and longitude. There is a scale factor, so that grid represents\r
-// latitude and longitude value parts more than ~ 1/182.0444,\r
-// and precision represents the rest of the values.\r
-\r
-// So we pull each 2n-th bit out, and shift it n places back to the nth longitudinal bit\r
-// and we pull each 2n-th+1 bit out, and shift it n+1 places to the nth latitudinal bit,\r
-\r
-       unsigned long int lat_mask=1;\r
-       unsigned long int lon_mask=2;\r
-       unsigned long int lat_val = 0;\r
-       unsigned long int lon_val = 0;\r
-       struct point p;\r
-\r
-       int i;\r
-       for(i=0; i<16; i++) {\r
-               lat_val += (lat_mask & msp.grid) >> i;\r
-               lon_val += (lon_mask & msp.grid) >> (i+1);\r
-               lat_mask <<= 2;\r
-               lon_mask <<= 2;\r
-       }\r
-\r
-       //printf("so far, lat_val=%d, lon_val=%d\n",lat_val ,lon_val);\r
-\r
-       // Dont divide by magic1 until accounting for precision,\r
-       // because that would introduce rounding errors\r
-       p.lat = (double) lat_val ;//  magic1;\r
-       p.lon = (double) lon_val ;//  magic1;\r
-\r
-       //printf("so far, got lat= %f lon= %f\n", p.lat, p.lon);\r
-\r
-       lat_mask=1;\r
-       lon_mask=2;\r
-       lat_val=0;\r
-       lon_val=0;\r
-\r
-       for (i=0; i<16; i++) {\r
-               lat_val += (lat_mask & msp.precision) >> i;\r
-               lon_val += (lon_mask & msp.precision) >> (i+1);\r
-               lat_mask <<= 2;\r
-               lon_mask <<= 2;\r
-       }\r
-\r
-       //printf("so far, lat_val=%d, lon_val=%d\n",lat_val ,lon_val);\r
-\r
-       p.lat += (double) lat_val / (magic2);\r
-       p.lon += (double) lon_val / (magic2);\r
-\r
-       p.lat *= 1/ (magic1);\r
-       p.lon *= 1/ (magic1);\r
-\r
-       //printf("so far, got lat= %f lon= %f\n", p.lat, p.lon);\r
-\r
-       if (p.lon > 180) p.lon -= 360;\r
-       if (p.lat > 180) p.lat -= 360;\r
-       return p;\r
-}\r
-\r
-void explore_annot(struct annot_rec rec)\r
-{\r
-       char* header;\r
-       char* tail;\r
-       int taillength;\r
-\r
-       header = (char*)xmalloc(ANNOT_REC_HEAD_LEN);\r
-       memcpy(header, rec.buf, ANNOT_RECOS_TEXT);\r
-       memcpy(header+ANNOT_RECOS_TEXT+2*rec.text_length, rec.buf,\r
-               ANNOT_REC_HEAD_LEN-ANNOT_RECOS_TEXT);\r
-\r
-       tail = rec.buf+ANNOT_REC_HEAD_LEN+2*rec.text_length;\r
-       taillength = rec.length - ANNOT_REC_HEAD_LEN+2*rec.text_length;\r
-\r
-       printf("Record buffer\n", annot_type_name[rec.type]);\r
-       printbuf(rec.buf, rec.length);\r
-       printf("Record high buffer\n", annot_type_name[rec.type]);\r
-       printbufhigh(rec.buf, rec.length);\r
-       printf("Record wide header:\n", annot_type_name[rec.type]);\r
-       printbufwide(header, ANNOT_REC_HEAD_LEN);\r
-       printf("Record tail:\n");\r
-       printbuf(tail, taillength);\r
-       printf("Record wide tail:\n");\r
-       printbufwide(tail, taillength);\r
-       printf("Record tail as floats:\n");\r
-       printbufasfloat(tail, taillength);\r
-       printf("Record tail as points:\n");\r
-       printbufaspoints(tail, taillength);\r
-//     if (rec.type == ANNOT_TYPE_TEXT)\r
-//     {\r
-               //printfloatbuf((float*)(tail+3), taillength/4 -1);\r
-//     }\r
-//     else if (rec.type == ANNOT_TYPE_OVAL )\r
-//             printfloatbuf((float*)(tail+3), taillength/4 -1);\r
-//     else if (rec.type == ANNOT_TYPE_CIRCLE ))\r
-//             printfloatbuf((float*)(tail+3), taillength/4 -1);\r
-       free(header);\r
-}\r
-\r
-void gpx_open_write_file_header(char* gpx_file_name)\r
-{\r
-       if (gpx_file_name)\r
-       {\r
-               gpx_file = fopen(gpx_file_name, "w");\r
-               if (gpx_file == NULL)\r
+               // FIXME saxcount complains that 0x1c is an invalid character, what else??\r
+               if ( (ustr[i]>127) || (ustr[i]==0x1c) )\r
                {\r
-                       fprintf(stderr, "Cannot open %s\n", optarg);\r
-                       exit(1);\r
+                       printf("Converting non-ascii char %c to space.\n", ustr[i]);\r
+                       str[i]=' ';\r
                }\r
-       }\r
-       else\r
-               return;\r
-\r
-       if (gpx_file!=NULL)\r
-       {\r
-               fprintf(gpx_file, GPX_HEADER1);\r
-               fprintf(gpx_file, GPX_HEADER2);\r
-               if (source_file_name)\r
-                       fprintf(gpx_file, "\t<desc>=\"This file was created from %s by %s\"</desc>\n",\r
-                                       source_file_name, GPX_THIS_PROGRAM);\r
-               // Some more tags we should add here\r
-               //      <name> Descriptive name of the GPX file\r
-               //      <desc> Description of the GPX file\r
-               //      <author> Name of the file's creator\r
-               //      <time> Creation date/time of the GPX file\r
-       }\r
-}\r
-\r
-void gpx_write_file_trailer()\r
-{\r
-       if (gpx_file!=NULL)\r
-       {\r
-               fprintf(gpx_file, GPX_FOOTER);\r
-           fclose(gpx_file);\r
-       }\r
-}\r
-\r
-void gpx_write_point(struct gpx_point pt, int pt_type, char* opt_elms)\r
-{\r
-       if (gpx_file!=NULL)\r
-       {\r
-               if (pt_type == GPX_TRKPT)\r
-                       fprintf(gpx_file, "\t\t");\r
-               else if (pt_type == GPX_RTEPT)\r
-                       fprintf(gpx_file, "\t");\r
-               fprintf(gpx_file, "\t<%s lat=\"%f\" lon=\"%f\">%s</%s>\n",\r
-                               gpxptypelabel[pt_type], pt.lat, pt.lon,\r
-                               opt_elms, gpxptypelabel[pt_type]);\r
-       }\r
-}\r
-\r
-void gpx_write_jour_point(struct jourwpt_rec * wpt)\r
-{\r
-       struct gpx_point pt;\r
-       char* opt_elms;\r
-       int optlen;\r
-\r
-       if (gpx_file==NULL)\r
-               return;\r
-\r
-       // For now we only deal with journey points which we matched to a pushpin.\r
-       // Later we need to allow for finding lat & lon in the journey stream itself\r
-       if (!wpt->pushpin)\r
-               return;\r
-       //printf("in gpx_write_jour_point\n");\r
-       //fflush(stdout);\r
-\r
-       optlen = strlen(wpt->pushpin->UdName) + strlen(wpt->pushpin->NoteShort) + 40;\r
-       opt_elms = (char*)xmalloc(optlen);\r
-\r
-       //printf("doing sprintf(opt_elms\n");\r
-       //fflush(stdout);\r
-\r
-       sprintf(opt_elms, "<name>%s</name><cmt>%s</cmt>",\r
-                       wpt->pushpin->UdName, wpt->pushpin->NoteShort);\r
-\r
-       pt.lat = wpt->pushpin->lat;\r
-       pt.lon = wpt->pushpin->lon;\r
-       pt.height = 0;\r
-\r
-       //printf("doing gpx_write_point\n");\r
-       //fflush(stdout);\r
-\r
-       gpx_write_point(pt, GPX_RTEPT, opt_elms);\r
-\r
-       free(opt_elms);\r
-\r
-       //printf("out of gpx_write_jour_point\n");\r
-       //fflush(stdout);\r
-\r
-}\r
-\r
-void gpx_write_jour_header()\r
-{\r
-       if(gpx_file!=NULL)\r
-       {\r
-               fprintf(gpx_file, "\t<rte>\n");\r
-               fprintf(gpx_file, "\t\t<name>Journey</name>\n");\r
-               fprintf(gpx_file, "\t\t<src>Extracted from main Journey</src>\n");\r
-       }\r
-}\r
-\r
-void gpx_write_jour_trailer()\r
-{\r
-       if(gpx_file!=NULL)\r
-               fprintf(gpx_file, "\t</rte>\n");\r
-\r
-}\r
-\r
-struct pushpin * ppin_by_UdId(int UdId)\r
-{\r
-       int i;\r
-\r
-       //printf("looking to match UdId %d to a pushpin\n", UdId);\r
-       //fflush(stdout);\r
-\r
-       if (UdId == 0)\r
-               return NULL;\r
-\r
-       for (i=0; i< MAX_PUSHPINS; i++)\r
-       {\r
-               //printf("Comparing to pushpin %d\n", i);\r
-               //fflush(stdout);\r
-               if(ppin_list[i] == NULL)\r
-                       return NULL;\r
-\r
-               //printf(" with UdId %ld ", (ppin_list[i])->UdId);\r
-               //fflush(stdout);\r
-               //printf(" and name %s\n", (ppin_list[i])->UdName);\r
-\r
-               if ((ppin_list[i]->UdId) == 0)\r
-                       return NULL;\r
-\r
-               if (ppin_list[i]->UdId == UdId)\r
-                       return ppin_list[i];\r
-       }\r
-\r
-       return NULL;\r
-}\r
-\r
-void gpx_write_pushpinlist ()\r
-{\r
-       int i;\r
-       struct gpx_point pt;\r
-       char* opt_elms;\r
-       int optlen;\r
-\r
-       if (gpx_file==NULL)\r
-               return;\r
-\r
-       for (i=0; i<MAX_PUSHPINS; i++)\r
-       {\r
-               if (ppin_list[i]==NULL)\r
-                       break;\r
-\r
-               optlen = strlen(ppin_list[i]->UdName) + strlen(ppin_list[i]->NoteShort) + 40;\r
-               opt_elms = (char*)xmalloc(optlen);\r
-\r
-               sprintf(opt_elms, "<name>%s</name><cmt>%s</cmt>",\r
-                               ppin_list[i]->UdName, ppin_list[i]->NoteShort);\r
-\r
-               pt.lat = ppin_list[i]->lat;\r
-               pt.lon = ppin_list[i]->lon;\r
-               pt.height = 0;\r
-\r
-               gpx_write_point(pt, GPX_WPT, opt_elms);\r
-       }\r
-       fprintf(gpx_file, "\n");\r
+       return str;\r
 }\r
 \r
-void gpx_write_annot_rec(struct annot_rec rec)\r
+char * strappend(char* str1, char* str2)\r
+// create a new string \r
 {\r
-       int pt_type;\r
-       int p;\r
-       char opt_elms[200];\r
-       struct gpx_point pt;\r
-\r
-       if (! gpx_file)\r
-       {\r
-               return;\r
-       }\r
-\r
-       pt_type = GPX_TRKPT ;\r
-\r
-       // FIXME why do I need to assign memory for this?\r
-\r
-       if (use_gpx_route)\r
-               pt_type = GPX_RTEPT;\r
-       switch (rec.type)\r
-       {\r
-               case ANNOT_TYPE_LINE:\r
-\r
-               // FIXME lots of format and name info to be added here\r
-               if(use_gpx_route)\r
-               {\r
-                       fprintf(gpx_file, "\t<rte>\n");\r
-                       fprintf(gpx_file, "\t\t<src>Extracted from Annotation %d (%s)</src>\n",\r
-                                       rec.annot_num, annot_type_name[rec.type]);\r
-                       fprintf(gpx_file, "\t\t<name>RT%04d</name>\n", rec.annot_num);\r
-               }\r
-               else\r
-               {\r
-                       fprintf(gpx_file, "\t<trk>\n");\r
-                       fprintf(gpx_file, "\t\t<name>TK%04d</name>\n", rec.annot_num);\r
-                       fprintf(gpx_file, "\t\t<src>Extracted from Annotation %d (%s)</src>\n",\r
-                                       rec.annot_num, annot_type_name[rec.type]);\r
-                       fprintf(gpx_file, "\t\t<trkseg>\n");\r
-               }\r
-\r
-               for (p=0; p < rec.line_points; p++)\r
-               {\r
-                       pt=gpx_get_point(rec.buf+annot_head_len[rec.type]+12*p);\r
-                       if(use_gpx_route)\r
-                               sprintf(opt_elms, "<name>rp%04d</name>", p);\r
-                       else\r
-                               // we need to include a name for trackpoints\r
-                               // for them to be recognised by easygps.\r
-                               sprintf(opt_elms, "<name>tp%04d</name>", p);\r
-                       gpx_write_point(pt, pt_type, opt_elms);\r
-               }\r
-               if(use_gpx_route)\r
-                       fprintf(gpx_file, "\t</rte>\n");\r
-               else\r
-                       fprintf(gpx_file, "\t\t</trkseg>\n\t</trk>\n");\r
-\r
-               case ANNOT_TYPE_OVAL:\r
-               case ANNOT_TYPE_TEXT:\r
-               case ANNOT_TYPE_CIRCLE:\r
-               default:\r
-                       break;\r
-       }\r
+       int len1=strlen(str1);\r
+       int len2=strlen(str2);\r
+       char* nw = (char*)xmalloc(len1 + len2 +1);\r
+       strcpy(nw, str1);\r
+       strcpy(nw+len1, str2);\r
+       return nw;\r
 }\r
 \r
 int readbytes(FILE* file, char* buf, int bytes2read)\r
 {\r
-       // cant I just do this with fread?\r
        int i;\r
-//     int status;\r
-/*     int readbyte;\r
-       for (i=0; i<bytes2read; i++)\r
-       {\r
-               readbyte = getc(file);\r
-               if(readbyte==EOF)\r
-               {\r
-               fprintf(stderr, "Unexpected end of file while reading %i bytes\n",bytes2read);\r
-               printf("Read %d of a required %d bytes\n", i+1, bytes2read);\r
-               printf("Dumping the buffer read before unexpected EOF\n");\r
-               printbuf(buf,i);\r
-               fflush(stdout);\r
-               return(1);\r
-               //exit(1);\r
-               }\r
-               buf[i] = readbyte;\r
-               if (verbose_flag > 5)\r
-               {\r
-                       //printf("read byte from file %#x=%u=%c\n", readbyte,readbyte,readbyte);\r
-                       //fflush(stdout);\r
-\r
-               }\r
-       }\r
-*/\r
        i = fread(buf, 1, bytes2read, file);\r
        if (i<bytes2read)\r
        {\r
@@ -761,541 +167,53 @@ int readbytes(FILE* file, char* buf, int bytes2read)
                        printf("Unexpected end of file\n");\r
                else if (ferror(file))\r
                        perror("Unexpected error while reading from file");\r
-        printf("Read %d of a required %d bytes\n", i+1, bytes2read);\r
+        printf("Read %d of a required %d bytes\n", i, bytes2read);\r
         printf("Dumping the buffer read before unexpected EOF or error\n");\r
         printbuf(buf,i);\r
-        fflush(stdout);\r
         return(i);\r
        }\r
 \r
-       if (verbose_flag > 5)\r
+       if (opts.verbose_flag > 5)\r
        {\r
                printf("Readbytes: Read %d bytes from file\n",bytes2read);\r
                printbuf(buf, bytes2read);\r
                fflush(stdout);\r
-               if (gpx_file)\r
-                       fflush(gpx_file);\r
-\r
        }\r
        return(i);\r
 }\r
 \r
-struct annot_rec read_annot_rec(int annot_num)\r
-{\r
-       // new improved version!\r
-\r
-       int status;\r
-       int i;\r
-       struct annot_rec rec;\r
-       rec.buf = (char*)xmalloc(ANNOT_REC_HEAD_LEN);\r
-       // This read can fail because I have miscalculated number of records\r
-       // So exit gracefully\r
-       status = readbytes(annot_file, rec.buf, ANNOT_REC_HEAD_LEN);\r
-       if (status!=ANNOT_REC_HEAD_LEN)\r
-       {\r
-               gpx_write_file_trailer();\r
-               // exit(1)\r
-               // should do some cleaning up here\r
-               return rec;\r
-       }\r
-\r
-       rec.type = *(int*)(rec.buf+ANNOT_RECOS_TYPE);\r
-       rec.annot_num = *(int*)(rec.buf+ANNOT_RECOS_ANUM);\r
-       rec.text_length = *(int*)(rec.buf+ANNOT_RECOS_TEXTLEN);\r
-       rec.line_points=0;\r
-       if (rec.type == ANNOT_TYPE_LINE)\r
-               rec.line_points = *(int*)(rec.buf+ANNOT_RECOS_LINENUMPOINTS);\r
-       rec.length = annot_rec_len[rec.type] + 2*rec.text_length + 12*rec.line_points;\r
-\r
-       printf("Got annotation %d with internal id %d, of type %s, text length %d, and %d line points\n",\r
-                       annot_num+1, rec.annot_num, annot_type_name[rec.type],\r
-                       rec.text_length, rec.line_points);\r
-\r
-       rec.buf = (char*)xrealloc(rec.buf, rec.length);\r
-       status = readbytes(annot_file, rec.buf+ANNOT_REC_HEAD_LEN, rec.length - ANNOT_REC_HEAD_LEN);\r
-       if (status!=(rec.length - ANNOT_REC_HEAD_LEN))\r
-       {\r
-               gpx_write_file_trailer();\r
-               exit(1);\r
-       }\r
-\r
-       if(rec.text_length>0)\r
-       {\r
-               rec.text=(char*)xmalloc(rec.text_length+1);\r
-               rec.text[rec.text_length]=0x0;\r
-               for (i=0;i<rec.text_length;i++)\r
-                       rec.text[i]=rec.buf[ANNOT_RECOS_TEXT+ 2*i];\r
-               //if (verbose_flag > 1)\r
-\r
-               printf("The sb text in the box is: %s\n", rec.text);\r
-       }\r
-\r
-       if (verbose_flag > 4)\r
-       {\r
-               printf("Recognised record with length %i\n",rec.length);\r
-               printbuf(rec.buf, rec.length);\r
-       }\r
-\r
-       return rec;\r
-}\r
-\r
-void process_annotations_stream(char* annot_file_name)\r
-{\r
-       // Read the annotation file header\r
-\r
-       int i;\r
-       int num_annotations;\r
-//     int file_pos = ANNOT_FILE_HEAD_LEN;\r
-       annot_file_header file_header = (annot_file_header)xmalloc(ANNOT_FILE_HEAD_LEN);\r
-       int status;\r
-       struct annot_rec rec;\r
-       char* checkEOF;\r
-\r
-       if ((annot_file = fopen(annot_file_name, "rb")) == NULL)\r
-       {\r
-               fprintf(stderr, "Quitting because I cannot open %s\n", annot_file_name);\r
-               exit(1);\r
-       }\r
-\r
-       status=readbytes(annot_file, file_header, ANNOT_FILE_HEAD_LEN);\r
-       if (status!=ANNOT_FILE_HEAD_LEN)\r
-       {\r
-               printf("Cant make any more sense of annotations stream, continuing\n");\r
-               return;\r
-       }\r
-\r
-    // file_pos is for debugging only\r
-\r
-       for (i=1; i<8; i++)\r
-               if ( file_header[i] != std_annotfile_header[i] )\r
-                       printf("Nonstandard annotations file header, header[%i]=0x%x, normal value is 0x%x\n",\r
-                                       i, file_header[i], std_annotfile_header[i] );\r
-\r
-       num_annotations = *(int*)(file_header+8);\r
-\r
-               if (verbose_flag > 1)\r
-               {\r
-                       printf("Annotations file header indicates %i annotations in file\n",\r
-                                       num_annotations);\r
-               }\r
-\r
-       if (verbose_flag > 4)\r
-       {\r
-               printf("Dumping file header:\n");\r
-               printbuf(file_header, ANNOT_FILE_HEAD_LEN);\r
-       }\r
-\r
-       /*\r
-       ** Read all the annotation records\r
-       */\r
-       for (i=0; i < num_annotations; i++)\r
-       {\r
-           rec = read_annot_rec(i);\r
-\r
-               if (explore_flag)\r
-                       explore_annot(rec);\r
-\r
-               gpx_write_annot_rec(rec);\r
-\r
-               free(rec.buf);\r
-               if (rec.text_length>0)\r
-                       free(rec.text);\r
-       }\r
-\r
-       // Check that we are at the end of annotation file\r
-\r
-       checkEOF = xmalloc(4);\r
-       status=readbytes(annot_file, checkEOF, 4);\r
-       if ( (status!=4) || (checkEOF[0]!=0) || (checkEOF[1]!=0)\r
-                       || (checkEOF[2]!=0) || (checkEOF[3]!=0) || (getc(annot_file)!=EOF) )\r
-       {\r
-               fprintf (stderr, "Did not finish reading annotation file at EOF\n");\r
-               if (gpx_file)\r
-                       fprintf(gpx_file, GPX_FOOTER);\r
-       }\r
-       free(checkEOF);\r
-       fclose(annot_file);\r
-       fflush(stdout);\r
-       fflush(gpx_file);\r
-}\r
-\r
-struct jourwpt_rec * read_journey_rec(int jour_num)\r
-{\r
-       int i;\r
-       int status;\r
-       int readlen1 = JOURWPT_REC_HEAD_LEN;\r
-       int readlen2;\r
-       int readlen3;\r
-       char c;\r
-       struct jourwpt_rec * rec = (struct jourwpt_rec *)xmalloc(sizeof(struct jourwpt_rec));\r
-\r
-       rec->buf = (char*)xmalloc(readlen1);\r
-\r
-       status = readbytes(jour_file, rec->buf, readlen1);\r
-       if (status!=readlen1)\r
-       {\r
-               printf("Unexpected EOF while reading Journey route point %d part 1.\n", jour_num);\r
-               printf("Dumping Journey route point buffer read so far\n");\r
-               printbuf(rec->buf, status);\r
-               //FIXME free rec\r
-               return NULL;\r
-       }\r
-\r
-       // FIXME careful here\r
-       c = rec->buf[0];\r
-       rec->UdId = c;\r
-\r
-       c = rec->buf[JOURWPT_RECOS_STR1LEN];\r
-\r
-       rec->text1_length = (int)c;\r
-\r
-       if (verbose_flag > 5)\r
-       {\r
-               printf("Reading Journey routepoint, got buf part1, text1 len = %d\n",\r
-                               rec->text1_length);\r
-               printbuf(rec->buf, readlen1);\r
-       }\r
-\r
-       readlen2 = rec->text1_length+4;\r
-\r
-       rec->buf = (char*)xrealloc(rec->buf, readlen1 + readlen2);\r
-       status = readbytes(jour_file, rec->buf+readlen1, readlen2);\r
-       if (status!=readlen2)\r
-       {\r
-               printf("Unexpected EOF while reading Journey route point %d part 2.\n", jour_num);\r
-               printf("Dumping Journey route point buffer read so far\n");\r
-               printbuf(rec->buf, readlen1+status);\r
-               //FIXME free rec\r
-               return NULL;\r
-       }\r
-\r
-       c = rec->buf[JOURWPT_RECOS_STR2LEN + rec->text1_length];\r
-       rec->text2_length = (int)c;\r
-       rec->buf_length = JOUR_WPTREC_LEN + rec->text1_length + 2*rec->text2_length;\r
-\r
-       if (verbose_flag > 5)\r
-       {\r
-               printf("got buf part2, text2 len = %d\n", rec->text2_length);\r
-               printbuf(rec->buf, readlen1 + readlen2);\r
-       }\r
-       readlen3 = rec->buf_length  - readlen1 - readlen2;\r
-\r
-       rec->buf = (char*)xrealloc(rec->buf, rec->buf_length);\r
-       status = readbytes(jour_file, rec->buf+readlen1+readlen2, readlen3);\r
-       if (status!=readlen3)\r
-       {\r
-               printf("Unexpected EOF while reading Journey route point %d part 3.\n", jour_num);\r
-               printf("Dumping Journey route point buffer read so far\n");\r
-               printbuf(rec->buf, readlen1+readlen2+status);\r
-               //FIXME free rec\r
-               return NULL;\r
-       }\r
-\r
-       rec->text1=(char*)xmalloc(rec->text1_length+1);\r
-       rec->text2=(char*)xmalloc(rec->text2_length+1);\r
-       rec->text1[rec->text1_length]=0;\r
-       rec->text2[rec->text2_length]=0;\r
-       memcpy(rec->text1, rec->buf+JOURWPT_RECOS_STR1, rec->text1_length);\r
-       for (i=0; i<rec->text2_length; i++)\r
-               rec->text2[i]=rec->buf[JOURWPT_RECOS_STR2 + rec->text1_length+2*i];\r
-\r
-       if (verbose_flag > 3)\r
-               printf("got Journey routepoint UdId %d, text1 '%s', text2 '%s', length %d\n",\r
-                       rec->UdId, rec->text1, rec->text2, rec->buf_length);\r
-\r
-       rec->pushpin = ppin_by_UdId(rec->UdId);\r
-\r
-       if (rec->pushpin != NULL)\r
-       {\r
-               if (verbose_flag > 5)\r
-               {\r
-                       printf("Found probable pushpin match\n");\r
-                       printf("pushpin name is: %s\n", rec->pushpin->UdName);\r
-                       printf("Pushpin short note is: %s\n", rec->pushpin->NoteShort);\r
-                       //printf("Pushpin long note is: %s\n", rec->pushpin->NoteLong);\r
-               }\r
-\r
-               gpx_write_jour_point(rec);\r
-       }\r
-       else\r
-       {\r
-               printf("*** Warning *** Ignoring route point '%s' without matching pushpin\n",\r
-                               rec->text1);\r
-               printf("(yes, I should do someting more clever than this).\n");\r
-               if (rec->UdId)\r
-                       printf("There should have been a matching pushin because UdId=%d\n", rec->UdId);\r
-       }\r
-       fflush(stdout);\r
-\r
-       if (verbose_flag > 4)\r
-       {\r
-               printf("Dumping the recognised Journey waypoint record\n");\r
-               printbuf(rec->buf, rec->buf_length);\r
-       }\r
-       return rec;\r
-}\r
-\r
-void process_journey_stream (char* jour_file_name)\r
-{\r
-       int journey_num_pts;\r
-       int j;\r
-       int readbyte;\r
-       static int verify_eof_flag = 0;\r
-       char* jour_file_header = (char*)xmalloc(JOUR_FILE_HEAD_LEN);\r
-       char* jour_file_trailer;\r
-       int max_read_more = 10000;\r
-       int readmore=0;\r
-       int status;\r
-       char readmorebuf[10000];\r
-       struct jourwpt_rec * rec;\r
-\r
-       gpx_write_jour_header();\r
-\r
-       printf("Processing Journey stream\n");\r
-       fflush(stdout);\r
-       fflush(gpx_file);\r
-\r
-\r
-       if ((jour_file = fopen(jour_file_name, "rb")) == NULL)\r
-       {\r
-               fprintf(stderr, "Quitting because I cannot open %s\n", jour_file_name);\r
-               exit(1);\r
-       }\r
-\r
-       status = readbytes(jour_file, jour_file_header, JOUR_FILE_HEAD_LEN);\r
-       if (status!=JOUR_FILE_HEAD_LEN)\r
-       {\r
-               printf("Unexpected EOF in the Journey stream\n");\r
-               gpx_write_jour_trailer();\r
-               return;\r
-       }\r
-\r
-       journey_num_pts = *(int*)(jour_file_header+JOUR_FILEOS_NUMREC);\r
-       printf("got Journey file header with %d waypoints\n", journey_num_pts);\r
-       if (verbose_flag > 4)\r
-       {\r
-               printbuf(jour_file_header, JOUR_FILE_HEAD_LEN);\r
-       }\r
-\r
-       for (j=0; j< journey_num_pts; j++)\r
-       {\r
-               rec = read_journey_rec(j);\r
-               if (rec==NULL)\r
-               {\r
-                       printf("Closing stream and skipping rest of Journey stream processing because I read a bad record\n");\r
-                       fclose(jour_file);\r
-                       printf("Writing gpx route for Journey\n");\r
-                       fflush(stdout);\r
-\r
-                       gpx_write_jour_trailer();\r
-\r
-                       printf("Finnished closing Journey stream after error.\n");\r
-                       return;\r
-               }\r
-       }\r
-\r
-       jour_file_trailer = (char*)xmalloc(JOUR_FILE_TAIL_LEN);\r
-\r
-       status = readbytes(jour_file, jour_file_trailer, JOUR_FILE_TAIL_LEN);\r
-       if (status!=JOUR_FILE_TAIL_LEN)\r
-       {\r
-               printf("Unexpected EOF while reading journey stream trailer\n");\r
-       }\r
-\r
-       if (verbose_flag > 4)\r
-       {\r
-               printf("got Journey file trailer\n");\r
-               printbuf(jour_file_trailer, JOUR_FILE_TAIL_LEN);\r
-       }\r
-\r
-       if ((readbyte = getc(jour_file))!=EOF)\r
-       {\r
-               fprintf (stderr, "Did not finish reading journey file at EOF\n");\r
-\r
-               do {\r
-                       readmorebuf[readmore]=(char)readbyte;\r
-                       readmore++;\r
-                       if (readmore>max_read_more)\r
-                               break;\r
-               } while ((readbyte = getc(jour_file))!=EOF);\r
-\r
-               printf("read a further %d bytes past expected eof\n",readmore);\r
-               printbuf(readmorebuf, readmore);\r
-       }\r
-\r
-    fclose(jour_file);\r
-       printf("Writing gpx route for Journey\n");\r
-       fflush(stdout);\r
-\r
-       gpx_write_jour_trailer();\r
-\r
-       printf("Finnished proccessing Journey stream.\n");\r
-       fflush(stdout);\r
-       fflush(gpx_file);\r
-}\r
-\r
-void read_ppin_list_csv(char* ppin_file_name)\r
-// for reading my old style csv temp file for ppins\r
-{\r
-       int pinnum;\r
-       int params_read;\r
-       char ppin_line[500+MAX_PPIN_MEMO];\r
-       char ppin_line_strings[500+MAX_PPIN_MEMO];\r
-       struct pushpin * ppin;\r
-       char* status;\r
-       int UdNameLen=0;\r
-       int NoteShortLen=0;\r
-       int NoteLongLen=0;\r
-\r
-       printf("Annalysing the pushpin temp file\n");\r
-\r
-       for (pinnum=0; pinnum < MAX_PUSHPINS; pinnum++)\r
-               ppin_list[pinnum] = NULL;\r
-\r
-       if ((ppin_file = fopen(ppin_file_name, "r")) == NULL)\r
-       {\r
-               fprintf(stderr, "Cannot open %s\n", ppin_file_name);\r
-               exit(1);\r
-       }\r
-\r
-       pinnum=0;\r
-       while (!feof( ppin_file))\r
-       {\r
-               //printf("Reading pushpin %d\n", pinnum);\r
-               //fflush(stdout);\r
-\r
-               ppin = (struct pushpin *)xmalloc(sizeof(struct pushpin));\r
-\r
-               status=fgets(ppin_line, 500+MAX_PPIN_MEMO, ppin_file);\r
-\r
-               if (status==NULL)\r
-               {\r
-                       printf("oops, trying to read empty line\n", pinnum);\r
-                       break;\r
-\r
-               }\r
-               else\r
-               {\r
-                       //printf("Read ppin temp line: %s\n", ppin_line);\r
-                       //fflush(stdout);\r
-\r
-                       params_read = sscanf(ppin_line, "%ld, %ld, %ld, %d, %d, %d, %[^\n]",\r
-                               &(ppin->UdId), &(ppin->Grid), &(ppin->Precision),\r
-                               &UdNameLen, &NoteShortLen, &NoteLongLen, ppin_line_strings);\r
-\r
-                       printf("Got pushpin UdId %ld Grid %d Precision %d ppin_line_strings %s\n",\r
-                                       ppin->UdId, ppin->Grid, ppin->Precision, ppin_line_strings);\r
-                       fflush(stdout);\r
-\r
-                       if (params_read == 7)\r
-                       {\r
-                               ppin->UdName = (char*)xmalloc(UdNameLen+1);\r
-                               memcpy(ppin->UdName, ppin_line_strings, UdNameLen);\r
-                               ppin->UdName[UdNameLen]=0;\r
-\r
-                               ppin->NoteShort = (char*)xmalloc(NoteShortLen+1);\r
-                               memcpy(ppin->NoteShort, ppin_line_strings+UdNameLen, NoteShortLen);\r
-                               ppin->NoteShort[NoteShortLen]=0;\r
-\r
-//                             ppin->NoteLong = (char*)xmalloc(NoteLongLen+1);\r
-//                             memcpy(ppin->NoteLong, ppin_line_strings+UdNameLen+NoteShortLen, NoteLongLen);\r
-//                             ppin->NoteLong[NoteLongLen]=0;\r
-\r
-                               //printf("Read %d parameters ok\n", params_read);\r
-                               //fflush(stdout);\r
-\r
-\r
-                               ppin_list[pinnum]=ppin;\r
-                       //      printf("saving pushpin_linst[%d]: UdId %ld lat %g lon %g UdName %s\n",\r
-                       //              pinnum, ppin->UdId, ppin->lat, ppin->lon, ppin->UdName);\r
-                       //      fflush(stdout);\r
-                               pinnum++;\r
-                       }\r
-                       else\r
-                       {\r
-                               printf("freeing this ppin (was# %d) because it did not read properly\n",\r
-                                               pinnum);\r
-                               free(ppin);\r
-                               break;\r
-                       }\r
-               }\r
-       }\r
-\r
-       fclose(ppin_file);\r
-       printf("Read %d pushpins, now writing to gpx\n", pinnum);\r
-\r
-}\r
-\r
-int check_file_empty(char* filename)\r
-{\r
-       int readchar;\r
-       FILE* file=fopen(filename, "rb");\r
-       // also check if the file exists\r
-       if (file==NULL)\r
-               return 1;\r
-       readchar = fgetc(file);\r
-       if (readchar == EOF)\r
-               return 1;\r
-       else\r
-               return 0;\r
-}\r
-\r
-void process_pushpin_file(char* ppin_file_name)\r
-{\r
-       int i=0;\r
-       struct point p;\r
-       struct ms_point msp;\r
-\r
-       // dont try and open a empty mdb file\r
-       if (check_file_empty(ppin_file_name))\r
-               return;\r
-\r
-       read_ppin_list(ppin_file_name);\r
-       //read_ppin_list_csv(ppin_file_name);\r
-\r
-       // set lat & lon for all pushpins\r
-       while(ppin_list[i] && (i<MAX_PUSHPINS))\r
-       {\r
-               msp.grid = ppin_list[i]->Grid;\r
-               msp.precision = ppin_list[i]->Precision;\r
-               p = ms2latlong(msp);\r
-\r
-               ppin_list[i]->lat = p.lat;\r
-               ppin_list[i]->lon = p.lon;\r
-\r
-       if (verbose_flag > 3)\r
-                       printf("Decoded pushpin %d lat %f, lon %f, UdName %s, NoteShort %s\n",\r
-                               ppin_list[i]->UdId, ppin_list[i]->lat, ppin_list[i]->lon,\r
-                               ppin_list[i]->UdName, ppin_list[i]->NoteShort);\r
-\r
-               i++;\r
-       }\r
-\r
-       gpx_write_pushpinlist();\r
-\r
-       printf("Finished reading pushpins\n");\r
-       fflush(stdout);\r
-       fflush(gpx_file);\r
-}\r
-\r
 void show_usage()\r
 {\r
        printf("st2gpx - Export data from MS Streets & Trips and Autoroute to GPX format\n\n");\r
+       // FIXME update this line\r
        printf("Usage: st2gpx [-hre] [-v verbose-level] [-a annotations-file] [-u userdata-file] ");\r
        printf("[-j journey-file] [-G gpx-file] stfile\n\n");\r
        printf("-h : Help (this text)\n");\r
        printf("-r : Export drawn-lines as routes instead of tracks\n");\r
-       printf("-e : Explore data furhter\n");\r
+       printf("-g gpx-in-file    : Import data from GPX XML format gpx-in-file\n");\r
+       printf("-G gpx-out-file   : Write output to GPX XML format gpx-out-file\n");\r
+       printf("-F st-mod-file    : Write modified stfile with imported data\n");\r
+       printf("                    to (new) st-mod-file.\n");\r
+       printf("-m mpst-in-file   : Import data from Garmin MapSource text-export mpst-in-file\n");\r
+       printf("-M pcx5-out-file  : Write output to Garmin MapSource importable pcx5-out-file\n");\r
+       printf("\n");\r
+       printf("export hint:\t st2gpx stfile (or use drag & drop)\n");\r
+       printf("import hint:\t st2gpx -g gpx-in-file -F st-mod-file st-template-file\n");\r
+//     printf("\n");\r
+       debug_pause();\r
+       printf("Debugging options:\n");\r
+       printf("-e : Explore data further\n");\r
        printf("-v [n]              : Set debugging verbosity to 'n' (0-6, default 2)\n");\r
        printf("-u userdata-file    : Process pushpins in (mdb) file userdata-file\n");\r
        printf("-j journey-file     : Process Journey in file journey-file\n");\r
        printf("-a annotations-file : Process Annotations in file annotations-file\n");\r
-       printf("-G gpx-file         : Write output to gpx-file\n");\r
+       printf("-p properties-file  : Analyse OLE properties-file\n");\r
+\r
+       debug_pause();\r
        exit(0);\r
 }\r
 \r
 void xsystem(char* syscmd)\r
-// this is not ANSI\r
 {\r
        int status;\r
        printf("%s \n", syscmd);\r
@@ -1308,38 +226,81 @@ void xsystem(char* syscmd)
 main(int argc, char** argv)\r
 {\r
        int c;\r
-       static int verify_eof_flag = 0;\r
-       char* jour_file_name=NULL;\r
-       char* annot_file_name=NULL;\r
-       char* ppin_file_name=NULL;\r
-       char* gpx_file_name=NULL;\r
+\r
+       char* jour_in_file_name=NULL;\r
+       char* annot_in_file_name=NULL;\r
+       char* ppin_in_file_name=NULL;\r
+       char* gpx_in_file_name=NULL;\r
+       char* gpx_out_file_name=NULL;\r
+       char* import_file_name=NULL;\r
+       char* properties_file_name=NULL;\r
+\r
+       char* contents_dir_name=NULL;\r
+       char source_full_path[_MAX_PATH];\r
+       char contents_full_path[_MAX_PATH];\r
+\r
+       char* mpst_in_file_name=NULL;\r
+       char* pcx5_out_file_name=NULL;\r
 \r
        char syscmd[1000];\r
     char cmddrv[_MAX_DRIVE];\r
     char cmddir[_MAX_DIR];\r
     char cmdfilename[_MAX_PATH];\r
     char cmdext[_MAX_EXT];\r
-       char cmdpath[_MAX_PATH];\r
+       char * cmdpath=NULL;\r
+\r
+\r
+       struct pushpin_safelist* ppplist=NULL;\r
+       struct journey* jour=NULL;\r
+       struct annotations* annots=NULL;\r
+       struct gpx_data* all_gpx=NULL;\r
+       struct ole_property_set * strips_properties=NULL;\r
+       struct ole_property * prop = NULL;\r
+       struct contents * conts;\r
+\r
+       char* temp_str=NULL;\r
+\r
+//     int verify_eof_flag = 0;\r
+\r
+       opts.explore_flag=0;\r
+       opts.use_gpx_route=0;\r
+       opts.verbose_flag=2;\r
+       opts.source_file_name=NULL;\r
+       opts.debug_wait_flag=0;\r
+       opts.st_version_num = 0;\r
+       opts.MapName = NULL;\r
+\r
+\r
+#ifdef MEMCHK\r
+       // Call _CrtCheckMemory at every allocation and deallocation request.\r
+       SET_CRT_DEBUG_FIELD(_CRTDBG_CHECK_ALWAYS_DF);\r
+       // Keep freed memory blocks in the heaps linked list, assign them the _FREE_BLOCK type, \r
+       // and fill them with the byte value 0xDD.\r
+       SET_CRT_DEBUG_FIELD(_CRTDBG_DELAY_FREE_MEM_DF);\r
+       // Perform automatic leak checking at program exit via a call to _CrtDumpMemoryLeaks \r
+       // and generate an error report if the application failed to free all the memory \r
+       // it allocated.\r
+       SET_CRT_DEBUG_FIELD(_CRTDBG_LEAK_CHECK_DF);\r
+#endif\r
+\r
+#ifdef DEBUG_STDOUT\r
+   _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );\r
+   _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT );\r
+   _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE );\r
+   _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDOUT );\r
+   _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE );\r
+   _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDOUT );\r
+#endif\r
+\r
+  // _CrtSetBreakAlloc(136);\r
 \r
-       int debug_wait_flag=0;\r
 \r
        while (1)\r
     {\r
-               static struct option long_options[] =\r
-        {\r
-                       {"file",    required_argument, 0, 'f'},\r
-                       {"outfile",    required_argument, 0, 'F'},\r
-                       {"verbose", optional_argument, 0, 'v'},\r
-                       {"explore", no_argument,       &explore_flag, 1},\r
-                       {"route",    no_argument, &use_gpx_route, 1},\r
-                       {0, 0, 0, 0} // what is this for?\r
-        };\r
                /* getopt_long stores the option index here. */\r
                int option_index = 0;\r
 \r
-               //    c = getopt_long (argc, argv, "v::bqderf:F:",\r
-               //                     long_options, &option_index);\r
-               c = getopt(argc, argv, "hu:j:a:G:rv::ew");\r
+               c = getopt(argc, argv, "hu:j:a:g:G:m:M:F:p:rv::ew");\r
 \r
                /* Detect the end of the options. */\r
                if (c == -1)\r
@@ -1357,54 +318,89 @@ main(int argc, char** argv)
 \r
         case 'u':\r
                        // read a UserData (pushpin) file directly\r
-                       free(ppin_file_name);\r
-                       ppin_file_name = (char*)xmalloc(strlen(optarg)+1);\r
-                       strcpy(ppin_file_name, optarg);\r
-                       if (verbose_flag > 1)\r
-                               printf("Analysing UserData (pushpin) stream in file %s\n\n", jour_file_name);\r
+                       free(ppin_in_file_name);\r
+                       ppin_in_file_name = (char*)xmalloc(strlen(optarg)+1);\r
+                       strcpy(ppin_in_file_name, optarg);\r
+                       if (opts.verbose_flag > 1)\r
+                               printf("Analysing UserData (pushpin) stream in file %s\n\n", jour_in_file_name);\r
            break;\r
 \r
        case 'j':\r
                        // read a Journey file directly\r
-                       free(jour_file_name);\r
-                       jour_file_name = (char*)xmalloc(strlen(optarg)+1);\r
-                       strcpy(jour_file_name, optarg);\r
-                       if (verbose_flag > 1)\r
-                               printf("Analysing Journey stream in file %s\n\n", jour_file_name);\r
+                       free(jour_in_file_name);\r
+                       jour_in_file_name = (char*)xmalloc(strlen(optarg)+1);\r
+                       strcpy(jour_in_file_name, optarg);\r
+                       if (opts.verbose_flag > 1)\r
+                               printf("Analysing Journey stream in file %s\n\n", jour_in_file_name);\r
             break;\r
 \r
         case 'a':\r
                        // read an annotation file directly\r
-                       annot_file_name = (char*)xmalloc(strlen(optarg)+1);\r
-                       strcpy(annot_file_name, optarg);\r
-                       if (verbose_flag > 1)\r
-                               printf("Analysing Annotation stream in file %s\n\n", annot_file_name);\r
+                       annot_in_file_name = (char*)xmalloc(strlen(optarg)+1);\r
+                       strcpy(annot_in_file_name, optarg);\r
+                       if (opts.verbose_flag > 1)\r
+                               printf("Analysing Annotation stream in file %s\n\n", annot_in_file_name);\r
+            break;\r
+\r
+        case 'g':\r
+                       gpx_in_file_name = (char*)xmalloc(strlen(optarg)+1);\r
+                       strcpy(gpx_in_file_name, optarg);\r
+                       if (opts.verbose_flag > 1)\r
+                               printf("Reading GPX from file %s\n\n", gpx_in_file_name);\r
             break;\r
 \r
         case 'G':\r
-                       gpx_file_name = (char*)xmalloc(200);\r
-                       strcpy(gpx_file_name, optarg);\r
-                       if (verbose_flag > 1)\r
-                               printf("Writing GPX output to file %s\n\n", gpx_file_name);\r
+                       gpx_out_file_name = (char*)xmalloc(strlen(optarg)+1);\r
+                       strcpy(gpx_out_file_name, optarg);\r
+                       if (opts.verbose_flag > 1)\r
+                               printf("Writing GPX output to file %s\n\n", gpx_out_file_name);\r
+            break;\r
+\r
+        case 'm':\r
+                       mpst_in_file_name = (char*)xmalloc(strlen(optarg)+1);\r
+                       strcpy(mpst_in_file_name, optarg);\r
+                       if (opts.verbose_flag > 1)\r
+                               printf("Reading Garmin MapSource Text format from file %s\n\n", mpst_in_file_name);\r
+            break;\r
+\r
+        case 'M':\r
+                       pcx5_out_file_name = (char*)xmalloc(strlen(optarg)+1);\r
+                       strcpy(pcx5_out_file_name, optarg);\r
+                       if (opts.verbose_flag > 1)\r
+                               printf("Writing Garmin MapSource importable pcx5 output to file %s\n\n", pcx5_out_file_name);\r
+            break;\r
+\r
+        case 'F':\r
+                       import_file_name = (char*)xmalloc(strlen(optarg)+1);\r
+                       strcpy(import_file_name, optarg);\r
+                       if (opts.verbose_flag > 1)\r
+                               printf("Writing modified s&t file with imported gpx data to file %s\n\n", import_file_name);\r
+            break;\r
+\r
+        case 'p':\r
+                       properties_file_name = (char*)xmalloc(strlen(optarg)+1);\r
+                       strcpy(properties_file_name, optarg);\r
+                       if (opts.verbose_flag > 1)\r
+                               printf("Analysing OLE Properties from file %s\n\n", properties_file_name);\r
             break;\r
 \r
         case 'r':\r
-                       use_gpx_route=1;\r
+                       opts.use_gpx_route=1;\r
             break;\r
 \r
                case 'v':\r
                        if (optarg==NULL)\r
-                               verbose_flag=5;\r
+                               opts.verbose_flag=5;\r
                        else\r
-                               verbose_flag = atoi(optarg);\r
+                               opts.verbose_flag = atoi(optarg);\r
                        break;\r
 \r
         case 'e':\r
-                       explore_flag = 1;\r
+                       opts.explore_flag = 1;\r
                        break;\r
 \r
         case 'w':\r
-                       debug_wait_flag = 1;\r
+                       opts.debug_wait_flag = 1;\r
                        break;\r
 \r
         case '?':\r
@@ -1420,44 +416,32 @@ main(int argc, char** argv)
 \r
        if (optind == argc-1)\r
        {\r
-                       source_file_name = (char*)xmalloc(strlen(argv[optind])+1);\r
-                       strcpy(source_file_name, argv[optind]);\r
-                       if (verbose_flag > 1)\r
-                               printf("Analysing autoroute file %s\n\n", source_file_name);\r
-                       if (ppin_file_name==NULL)\r
-                       {\r
-                               ppin_file_name = (char*)xmalloc(strlen(source_file_name)+30);\r
-                               sprintf(ppin_file_name, "%s.Contents\\UserData.mdb", source_file_name);\r
-                       }\r
-                       if (jour_file_name==NULL)\r
-                       {\r
-                               jour_file_name = (char*)xmalloc(strlen(source_file_name)+30);\r
-                               sprintf(jour_file_name, "%s.Contents\\Journey", source_file_name);\r
-                       }\r
-                       if (annot_file_name==NULL)\r
-                       {\r
-                               annot_file_name = (char*)xmalloc(strlen(source_file_name)+30);\r
-                               sprintf(annot_file_name, "%s.Contents\\Annotations", source_file_name);\r
-                       }\r
-                       if (gpx_file_name==NULL)\r
-                       {\r
-                               gpx_file_name = (char*)xmalloc(strlen(source_file_name)+30);\r
-                               // should remove the est or axe suffix\r
-                               sprintf(gpx_file_name, "%s.gpx", source_file_name);\r
-                       }\r
+                       opts.source_file_name = (char*)xmalloc(strlen(argv[optind])+1);\r
+                       strcpy(opts.source_file_name, argv[optind]);\r
+                       if (opts.verbose_flag > 1)\r
+                               printf("Analysing autoroute file %s\n\n", opts.source_file_name);\r
+                       if (ppin_in_file_name==NULL)\r
+                               ppin_in_file_name = strappend(opts.source_file_name, ".Contents\\UserData.mdb");\r
+                       if (jour_in_file_name==NULL)\r
+                               jour_in_file_name = strappend(opts.source_file_name, ".Contents\\Journey");\r
+                       if (annot_in_file_name==NULL)\r
+                               annot_in_file_name = strappend(opts.source_file_name, ".Contents\\Annotations");\r
+                       if ((gpx_out_file_name==NULL) && (gpx_in_file_name==NULL))\r
+                               gpx_out_file_name = strappend(opts.source_file_name, ".gpx");\r
        }\r
        else if (optind < argc-1)\r
        {\r
            printf("Unrecognised option %s\n", argv[optind+1]);\r
                show_usage();\r
-    }\r
+\r
+       }\r
        else\r
        {\r
-               if (verbose_flag > 1)\r
+               if (opts.verbose_flag > 1)\r
                        printf("Not analysing any core S&T or autoroute file\n");\r
        }\r
 \r
-       if (source_file_name)\r
+       if (opts.source_file_name)\r
        {\r
                // Open the compound file using the istorage utility\r
                // I probably should do this in a library and use streams instead of files\r
@@ -1466,58 +450,192 @@ main(int argc, char** argv)
 \r
                // this is not ANSI\r
                _splitpath(argv[0], cmddrv, cmddir, cmdfilename, cmdext);\r
-               sprintf(cmdpath, "%s%s", cmddrv, cmddir);\r
+               //sprintf(cmdpath, "%s%s", cmddrv, cmddir);\r
+               cmdpath = strappend(cmddrv, cmddir);\r
 \r
-               sprintf(syscmd, "%sistorage\\istorage.exe %s", cmdpath, source_file_name);\r
-               xsystem(syscmd);\r
+               _fullpath(source_full_path, opts.source_file_name, _MAX_PATH);\r
 \r
-               // clean up previous copy of this. It should already have been deleted...\r
-               sprintf(syscmd, "del %s.Contents\\UserData.mdb", source_file_name);\r
+               sprintf(syscmd, "%sistorage\\istorage.exe \"%s\"", cmdpath, source_full_path);\r
                xsystem(syscmd);\r
 \r
-               sprintf(syscmd, "rename %s.Contents\\UserData. UserData.mdb", source_file_name);\r
+               printf("*****************************************************************\n");\r
+               printf("Finished istorage command\n");\r
+\r
+               sprintf(syscmd, "rename \"%s.Contents\\UserData.\" UserData.mdb", opts.source_file_name);\r
                xsystem(syscmd);\r
        }\r
 \r
+       // ***************************\r
        // begin processing the files\r
-       gpx_open_write_file_header(gpx_file_name);\r
+       // ***************************\r
 \r
-       if (ppin_file_name)\r
-               process_pushpin_file(ppin_file_name);\r
-       if (jour_file_name)\r
-               process_journey_stream(jour_file_name);\r
-       if (annot_file_name)\r
-               process_annotations_stream(annot_file_name);\r
+       // Read GPX import file\r
+       if (gpx_in_file_name)\r
+       {\r
+               all_gpx = process_gpx_in_file(gpx_in_file_name);\r
+               if (all_gpx==NULL)\r
+                       printf("Didn't read any usable data from %s ???\n",gpx_in_file_name);\r
+               printf("Read %d waypoints, %d routes and %d tracks from file %s\n", all_gpx->wpt_list_count, all_gpx->rte_list_count, all_gpx->trk_list_count, gpx_in_file_name);\r
+               printf("Importing this data as %d lines\n", all_gpx->rte_list_count + all_gpx->trk_list_count);\r
+       }\r
 \r
-       gpx_write_file_trailer();\r
+       // Read Mapsource text-export file.\r
+       // Does it make any sense to try and merge with all_gpx from above? Not for now...\r
+       if (mpst_in_file_name)\r
+       {\r
+               gpx_data_delete(all_gpx);\r
+               all_gpx = read_mpstext(mpst_in_file_name);\r
+               if (all_gpx==NULL)\r
+                       printf("Didn't read any usable data from %s ???\n",mpst_in_file_name);\r
+               printf("Read %d waypoints, %d routes and %d tracks from file %s\n",\r
+                               all_gpx->wpt_list_count, all_gpx->rte_list_count, \r
+                               all_gpx->trk_list_count, mpst_in_file_name);\r
+               printf("Importing this data as %d lines\n", \r
+                               all_gpx->rte_list_count + all_gpx->trk_list_count);\r
+       }\r
 \r
+       // ole properties from S&T source file\r
+       if (opts.source_file_name)\r
+       {\r
+               strips_properties=read_ole_properties(opts.source_file_name, NULL);\r
+               prop = get_propterty(strips_properties, 0x60002);\r
+               if ((prop!=NULL) && (prop->buf != NULL) )\r
+               {\r
+                       opts.st_version_num = *(int*)(prop->buf); \r
+                       printf("Autoroute/S&T version in %s is %d\n", opts.source_file_name, opts.st_version_num);\r
+               }\r
+               prop = get_propterty(strips_properties, 0x10000);\r
+               if ((prop!=NULL) && (prop->buf != NULL) )\r
+               {\r
+                       opts.MapName = (WCHAR*)(prop->buf + 4); \r
+                       wprintf(L"MapName is %ls\n", opts.MapName);\r
+                       if(wcscmp(opts.MapName, L"USA")==0)\r
+                               opts.isUSA=1;\r
+                       else if(wcscmp(opts.MapName, L"EUR")!=0 )\r
+                               printf("Unknown map type, assuming EUR\n");\r
+               }\r
+       }\r
 \r
-       // Clean up the compound file directory\r
-       if (source_file_name)\r
+       // check the contents stream\r
+       //if(opts.explore_flag)\r
        {\r
-               sprintf(syscmd, "echo y|del %s.Contents", source_file_name);\r
-               xsystem(syscmd);\r
+               temp_str = strappend(opts.source_file_name, ".Contents\\Contents");\r
+               conts = read_contents(temp_str);\r
+               free(temp_str);\r
+               temp_str=NULL;\r
+       }\r
+\r
+       // ole properties from any file, just for debuging\r
+       if (properties_file_name)\r
+               ole_property_set_delete(read_ole_properties(NULL,opts.source_file_name));\r
+\r
+       // read the data in the S&T source file\r
+       if (ppin_in_file_name)\r
+               ppplist = process_pushpin_file(ppin_in_file_name);\r
+       if (jour_in_file_name)\r
+               jour = process_journey_stream(jour_in_file_name, ppplist);\r
+       if (annot_in_file_name)\r
+               annots = process_annotations_stream(annot_in_file_name);\r
+\r
+       // export GPX\r
+       if ( (gpx_out_file_name) && (all_gpx==NULL) )\r
+               gpx_write_all(gpx_out_file_name, ppplist, jour, annots);\r
 \r
-       // just for debuging\r
-       if (debug_wait_flag)\r
+       // export Mapsource pcx5\r
+       if (pcx5_out_file_name)\r
+               pcx5_export(pcx5_out_file_name, ppplist, jour, annots);\r
+\r
+       // Merge the data in the S&T source file with any imported GPX/mapsource data\r
+       if ((all_gpx!=NULL) && (opts.source_file_name!=NULL))\r
        {\r
-               fprintf(stderr, "kill that ado connection!\n");\r
-               fprintf(stderr, "Hit any key to continue\n");\r
-               getchar();\r
+               merge_gpx_annot(annots, all_gpx);\r
+               if (annots==NULL)\r
+                       printf("After merging data, dont have any annotations???\n");\r
+               printf("After merging data, there are %d annotations\n", annots->num_annotations);\r
+               //print_annotations(annots);\r
+               write_annotations(annots, annot_in_file_name);\r
+               //print_annotations(annots);\r
+\r
+               // ********************\r
+               // This is experimantal\r
+               // ********************\r
+               temp_str = strappend(opts.source_file_name, ".Contents\\Contents");\r
+               write_pushpins_from_gpx(ppin_in_file_name, all_gpx, conts, temp_str);\r
+               free(temp_str);\r
+               temp_str=NULL;\r
        }\r
 \r
-               // how do I do this?\r
-               sprintf(syscmd, "del %s.Contents\\UserData.mdb", source_file_name);\r
+       // create the s&t/autoroute file from the modified parts\r
+       if ((opts.source_file_name!=NULL) && (all_gpx!=NULL) && (import_file_name!=NULL))\r
+       {\r
+               // Actually, we should allow NULL import_file_name and invent a sensible name\r
+\r
+               sprintf(syscmd, "rename %s.Contents\\UserData.mdb UserData.", opts.source_file_name);\r
                xsystem(syscmd);\r
 \r
-               sprintf(syscmd, "rmdir %s.Contents", source_file_name);\r
+               contents_dir_name=(char*)xmalloc(strlen(opts.source_file_name)+20);\r
+               sprintf(contents_dir_name, "%s.Contents", opts.source_file_name);\r
+\r
+               _fullpath(contents_full_path, contents_dir_name, _MAX_PATH);\r
+\r
+               sprintf(syscmd, "%sistorage\\istorage-make.exe \"%s\"", cmdpath, contents_full_path);\r
                xsystem(syscmd);\r
+\r
+               printf("*****************************************************************\n");\r
+               printf("Finished istorage-make command\n");\r
+\r
+               sprintf(syscmd, "del \"%s\"", import_file_name);\r
+               xsystem(syscmd);\r
+\r
+               _splitpath(opts.source_file_name, cmddrv, cmddir, cmdfilename, cmdext);\r
+               sprintf(syscmd, "move \"%s.Contents.ole\" \"%s\"", opts.source_file_name, import_file_name);\r
+               xsystem(syscmd);\r
+\r
        }\r
 \r
-       // just for debuging\r
-       if (debug_wait_flag)\r
+    // Clean up the compound file directory\r
+       if (opts.source_file_name)\r
        {\r
-               fprintf(stderr, "Hit any key to continue\n");\r
-               getchar();\r
+               {\r
+                       sprintf(syscmd, "echo y|del \"%s.Contents\"", opts.source_file_name);\r
+                       xsystem(syscmd);\r
+\r
+                       sprintf(syscmd, "rmdir \"%s.Contents\"", opts.source_file_name);\r
+                       xsystem(syscmd);\r
+               }\r
        }\r
+\r
+       // free variables. Not really necessary.\r
+       annotations_delete(annots);\r
+       pushpin_safelist_delete(ppplist);\r
+       journey_delete(jour);\r
+       gpx_data_delete(all_gpx);\r
+       ole_property_set_delete(strips_properties);\r
+       contents_delete(conts);\r
+\r
+       xfree(cmdpath);\r
+       xfree(ppin_in_file_name);\r
+       xfree(jour_in_file_name);\r
+       xfree(annot_in_file_name);\r
+       xfree(gpx_in_file_name);\r
+       xfree(gpx_out_file_name);\r
+       xfree(pcx5_out_file_name);\r
+       xfree(import_file_name);\r
+       xfree(opts.source_file_name);\r
+       xfree(contents_dir_name);\r
+       xfree(mpst_in_file_name);\r
+       \r
+       if (opts.verbose_flag>5)\r
+               printf("Done freeing all\n");\r
+\r
+       //debug_show_sizes();\r
+       //debug_pause();\r
+       //printf("exiting main\n");\r
+\r
+       _flushall();\r
+\r
+#ifdef _DEBUG\r
+//     _CrtDumpMemoryLeaks();  \r
+#endif\r
+       debug_pause();\r
 }\r
index 14589899a984a0bd9516564c6ca387839794865a..1d369b1a64152ecb2300a6e8a623b38cf19d64df 100644 (file)
@@ -39,9 +39,10 @@ RSC=rc.exe
 # PROP Use_Debug_Libraries 0\r
 # PROP Output_Dir "Release"\r
 # PROP Intermediate_Dir "Release"\r
+# PROP Ignore_Export_Lib 0\r
 # PROP Target_Dir ""\r
 # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c\r
-# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c\r
+# ADD CPP /nologo /Zp1 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c\r
 # ADD BASE RSC /l 0x409 /d "NDEBUG"\r
 # ADD RSC /l 0x409 /d "NDEBUG"\r
 BSC32=bscmake.exe\r
@@ -49,7 +50,7 @@ BSC32=bscmake.exe
 # ADD BSC32 /nologo\r
 LINK32=link.exe\r
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r
+# ADD LINK32 libexpat.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r
 \r
 !ELSEIF  "$(CFG)" == "st2gpx - Win32 Debug"\r
 \r
@@ -62,9 +63,10 @@ LINK32=link.exe
 # PROP Use_Debug_Libraries 1\r
 # PROP Output_Dir "Debug"\r
 # PROP Intermediate_Dir "Debug"\r
+# PROP Ignore_Export_Lib 0\r
 # PROP Target_Dir ""\r
 # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c\r
-# ADD CPP /nologo /W4 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c\r
+# ADD CPP /nologo /Zp1 /Za /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c\r
 # ADD BASE RSC /l 0x409 /d "_DEBUG"\r
 # ADD RSC /l 0x409 /d "_DEBUG"\r
 BSC32=bscmake.exe\r
@@ -72,7 +74,8 @@ BSC32=bscmake.exe
 # ADD BSC32 /nologo\r
 LINK32=link.exe\r
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
+# ADD LINK32 libexpat.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
+# SUBTRACT LINK32 /profile /map\r
 \r
 !ENDIF \r
 \r
@@ -85,7 +88,53 @@ LINK32=link.exe
 # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
 # Begin Source File\r
 \r
+SOURCE=.\annotations.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\contents.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\debug.c\r
+# End Source File\r
+# Begin Source File\r
+\r
 SOURCE=.\getopt.c\r
+\r
+!IF  "$(CFG)" == "st2gpx - Win32 Release"\r
+\r
+!ELSEIF  "$(CFG)" == "st2gpx - Win32 Debug"\r
+\r
+# ADD CPP /Ze\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\journey.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\nannol.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\ppinutil.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\properties.c\r
+\r
+!IF  "$(CFG)" == "st2gpx - Win32 Release"\r
+\r
+!ELSEIF  "$(CFG)" == "st2gpx - Win32 Debug"\r
+\r
+# ADD CPP /Ze\r
+\r
+!ENDIF \r
+\r
 # End Source File\r
 # Begin Source File\r
 \r
@@ -95,13 +144,21 @@ SOURCE=.\pushpins.cpp
 \r
 !ELSEIF  "$(CFG)" == "st2gpx - Win32 Debug"\r
 \r
-# ADD CPP /W4\r
+# ADD CPP /Ze /W4 /Gi\r
 \r
 !ENDIF \r
 \r
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE=.\readgpx.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\readmpst.c\r
+# End Source File\r
+# Begin Source File\r
+\r
 SOURCE=.\st2gpx.c\r
 \r
 !IF  "$(CFG)" == "st2gpx - Win32 Release"\r
@@ -112,6 +169,14 @@ SOURCE=.\st2gpx.c
 \r
 !ENDIF \r
 \r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\writegpx.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\writepcx.c\r
 # End Source File\r
 # End Group\r
 # Begin Group "Header Files"\r
@@ -119,16 +184,60 @@ SOURCE=.\st2gpx.c
 # PROP Default_Filter "h;hpp;hxx;hm;inl"\r
 # Begin Source File\r
 \r
+SOURCE=.\annotations.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\contents.h\r
+# End Source File\r
+# Begin Source File\r
+\r
 SOURCE=.\getopt.h\r
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE=.\gpx.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\journey.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\ppinutil.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\properties.h\r
+# End Source File\r
+# Begin Source File\r
+\r
 SOURCE=.\pushpins.h\r
 # End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\st2gpx.h\r
+# End Source File\r
 # End Group\r
 # Begin Group "Resource Files"\r
 \r
 # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"\r
 # End Group\r
+# Begin Source File\r
+\r
+SOURCE=.\bugs.txt\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\build.txt\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\history.txt\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\ToDo.txt\r
+# End Source File\r
 # End Target\r
 # End Project\r
index 19486fe9c2ac29ad3239f719b690590222f358e6..c71a2e211470ca3ff9ab9853a3fdd54b1948d722 100644 (file)
@@ -3,18 +3,6 @@ Microsoft Developer Studio Workspace File, Format Version 6.00
 \r
 ###############################################################################\r
 \r
-Project: "VCADO"="..\..\..\sw\5191\Rosetta\CPP\#Import-upg\Vcado.dsp" - Package Owner=<4>\r
-\r
-Package=<5>\r
-{{{\r
-}}}\r
-\r
-Package=<4>\r
-{{{\r
-}}}\r
-\r
-###############################################################################\r
-\r
 Project: "st2gpx"=.\st2gpx.dsp - Package Owner=<4>\r
 \r
 Package=<5>\r
diff --git a/st2gpx/src/st2gpx.h b/st2gpx/src/st2gpx.h
new file mode 100644 (file)
index 0000000..667b1a3
--- /dev/null
@@ -0,0 +1,142 @@
+/*\r
+       st2gpx.h\r
+\r
+       Extract data from MS Streets & Trips .est and Autoroute .axe files in GPX format.\r
+\r
+    Copyright (C) 2003 James Sherring, james_sherring@yahoo.com\r
+\r
+    This program is free software; you can redistribute it and/or modify\r
+    it under the terms of the GNU General Public License as published by\r
+    the Free Software Foundation; either version 2 of the License, or\r
+    (at your option) any later version.\r
+\r
+    This program is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+\r
+    You should have received a copy of the GNU General Public License\r
+    along with this program; if not, write to the Free Software\r
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA\r
+\r
+\r
+       This app depends on istorage & istorage-make from Pabs (pabs3@zip.to)\r
+       and James Clark's Expat xml parser from http://www.libexpat.org/.\r
+\r
+*/\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+#define MEMCHK\r
+#define DEBUG_STDOUT\r
+//#define MEMTRACE\r
+\r
+#ifdef _DEBUG\r
+#define _CRTDBG_MAP_ALLOC\r
+#define  SET_CRT_DEBUG_FIELD(a)   _CrtSetDbgFlag((a) | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG))\r
+#define  CLEAR_CRT_DEBUG_FIELD(a) _CrtSetDbgFlag(~(a) & _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG))\r
+#else\r
+#define  SET_CRT_DEBUG_FIELD(a)   ((void) 0)\r
+#define  CLEAR_CRT_DEBUG_FIELD(a) ((void) 0)\r
+#endif\r
+\r
+#ifndef M_PI\r
+#define M_PI 3.14159265358979323846 \r
+#endif\r
+\r
+typedef unsigned short WCHAR;\r
+\r
+//#define ST_VERSION_AUTOROUTE2001     1\r
+//#define ST_VERSION_STREETSTRIPS2000 2\r
+//#define ST_VERSION_STREETSTRIPS2001 3\r
+\r
+//#define ST_VERSION_AUTOROUTE2002     4\r
+//#define ST_VERSION_AUTOROUTE2003     5\r
+//#define ST_VERSION_STREETSTRIPS2002 6\r
+//#define ST_VERSION_STREETSTRIPS2003 7\r
+\r
+typedef struct st2gpx_options \r
+{\r
+       // 0 - only errors\r
+       // 1 also the structured data output, e.g. line point info\r
+       // 2 also record types & parameters\r
+       // 3 also detailed summary info\r
+       // 4 also detailed analysis of headers & record params\r
+       // 5 also dump buffers\r
+       // 6 lots of debug info\r
+       int verbose_flag;\r
+       int explore_flag;\r
+       // force line-type annotations to be exported as GPX routes instead of tracks\r
+       int use_gpx_route;\r
+       char* source_file_name;\r
+       // wait for enter key at certain points in the program\r
+       int debug_wait_flag;\r
+       int st_version_num;\r
+       WCHAR* MapName;\r
+       // 0 for EUR, i.e. Autoroute\r
+       // 1 for USA, i,e, Streets & Trips\r
+       unsigned char isUSA;\r
+} tag_st2gpx_options;\r
+\r
+\r
+// FIXME is this the correct way to forward define these?\r
+#ifndef        __cplusplus\r
+\r
+extern struct point;\r
+extern struct pushpin;\r
+extern struct annotations;\r
+extern struct pushpin_safelist;\r
+extern struct annot_rec ;\r
+extern struct gpx_data;\r
+extern struct f_jour_pt_head;\r
+extern struct f_jour_pt_tail;\r
+extern struct f_jour_opts_EUR_8;\r
+extern struct f_jour_opts_EUR_10;\r
+extern struct f_jour_opts_USA_8;\r
+extern struct f_jour_opts_USA_10;\r
+extern struct f_jour_opts;\r
+extern struct f_jour_avoid;\r
+extern struct f_jour_trailer;\r
+extern struct journey;\r
+extern struct f_jour_header;\r
+extern struct contents;\r
+\r
+#endif // __cplusplus\r
\r
+//st2gpx.c\r
+extern struct st2gpx_options opts;\r
+void * xmalloc(size_t size);\r
+void * xrealloc(void* ptr, size_t size);\r
+void xfree(void * obj);\r
+char * str2ascii(char* str);\r
+int readbytes(FILE* file, char* buf, int bytes2read);\r
+//nannol.c\r
+struct annotations * merge_gpx_annot(struct annotations * annots, struct gpx_data* all_gpx);\r
+void write_annotations(struct annotations * annots, char* annot_out_file_name);\r
+//writepcx.c\r
+void pcx5_export(char* pcx5_out_file_name, struct pushpin_safelist * ppplist, struct journey * jour, struct annotations * pannots);\r
+//debug.c\r
+void debug_pause();\r
+void printbuf(char* buf, int len);\r
+void explore_annot(struct annot_rec * rec);\r
+void print_f_jour_header(struct f_jour_header * head);\r
+void print_f_jour_pt_head(struct f_jour_pt_head * pt_head);\r
+void print_f_jour_pt_tail(struct f_jour_pt_tail * pt_tail);\r
+void print_f_jour_opts(struct f_jour_opts * jopts);\r
+void print_f_jour_opts_EUR_8(struct f_jour_opts_EUR_8 * jopts);\r
+void print_f_jour_opts_EUR_10(struct f_jour_opts_EUR_10 * jopts);\r
+void print_f_jour_opts_USA_8(struct f_jour_opts_USA_8 * jopts);\r
+void print_f_jour_opts_USA_10(struct f_jour_opts_USA_10 * jopts);\r
+void print_f_jour_avoid(struct f_jour_avoid * avoid);\r
+void print_f_jour_trailer(struct f_jour_trailer * trailer);\r
+void print_annot_rec(struct annot_rec * rec);\r
+void print_annotations(struct annotations * annots);\r
+void debug_show_sizes();\r
+//st2gpx.c\r
+struct gpx_data * read_mpstext(char* mpstxt_file_name);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
diff --git a/st2gpx/src/writegpx.c b/st2gpx/src/writegpx.c
new file mode 100644 (file)
index 0000000..34bbcdf
--- /dev/null
@@ -0,0 +1,317 @@
+/*\r
+       writegpx.c\r
+\r
+       Extract data from MS Streets & Trips .est and Autoroute .axe files in GPX format.\r
+\r
+    Copyright (C) 2003 James Sherring, james_sherring@yahoo.com\r
+\r
+    This program is free software; you can redistribute it and/or modify\r
+    it under the terms of the GNU General Public License as published by\r
+    the Free Software Foundation; either version 2 of the License, or\r
+    (at your option) any later version.\r
+\r
+    This program is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+\r
+    You should have received a copy of the GNU General Public License\r
+    along with this program; if not, write to the Free Software\r
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA\r
+\r
+\r
+       This app depends on istorage & istorage-make from Pabs (pabs3@zip.to)\r
+       and James Clark's Expat xml parser from http://www.libexpat.org/.\r
+\r
+*/\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+\r
+#include "st2gpx.h"\r
+#include "gpx.h"\r
+#include "ppinutil.h"\r
+#include "journey.h"\r
+#include "annotations.h"\r
+\r
+#define GPX_HEADER1 "<?xml version=\"1.0\" standalone=\"yes\"?>\n<gpx version=\"1.0\" \n  xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n  xmlns=\"http://www.topografix.com/GPX/1/0\"\n  xsi:schemaLocation=\"http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd\"\n "\r
+#define GPX_HEADER2 " creator=\"st2gpx-james_sherring@yahoo.com\">\n"\r
+#define GPX_THIS_PROGRAM "st2gpx from james_sherring@yahoo.com"\r
+#define GPX_FOOTER "</gpx>"\r
+\r
+#define GPX_WPT 0\r
+#define GPX_RTEPT 1\r
+#define GPX_TRKPT 2\r
+char * gpxptypelabel[3] = {"wpt", "rtept", "trkpt"};\r
+\r
+FILE* gpx_open_write_file_header(char* gpx_out_file_name)\r
+{\r
+       FILE* gpx_out_file=NULL;\r
+\r
+       if (gpx_out_file_name)\r
+       {\r
+               gpx_out_file = fopen(gpx_out_file_name, "w");\r
+               if (gpx_out_file == NULL)\r
+               {\r
+                       fprintf(stderr, "Cannot open %s\n", gpx_out_file_name);\r
+                       debug_pause();\r
+                       exit(1);\r
+               }\r
+       }\r
+       else\r
+               return NULL;\r
+\r
+       if (gpx_out_file!=NULL)\r
+       {\r
+               fprintf(gpx_out_file, GPX_HEADER1);\r
+               fprintf(gpx_out_file, GPX_HEADER2);\r
+               if (opts.source_file_name)\r
+                       fprintf(gpx_out_file, "\t<desc>This file was created from %s by %s</desc>\n",\r
+                                       opts.source_file_name, GPX_THIS_PROGRAM);\r
+               // Some more tags we should add here\r
+               //      <name> Descriptive name of the GPX file\r
+               //      <desc> Description of the GPX file\r
+               //      <author> Name of the file's creator\r
+               //      <time> Creation date/time of the GPX file\r
+       }\r
+       return gpx_out_file;\r
+}\r
+\r
+void gpx_write_file_trailer(FILE* gpx_out_file)\r
+{\r
+       if (gpx_out_file!=NULL)\r
+       {\r
+               fprintf(gpx_out_file, GPX_FOOTER);\r
+           fclose(gpx_out_file);\r
+       }\r
+}\r
+\r
+void gpx_write_point(FILE* gpx_out_file, struct gpxpt * pt, int pt_type, char* opt_elms)\r
+// FIXEM do <name> from pt, not from opt_elms\r
+// FIXME same for other atts defined in gpxpt\r
+{\r
+       if (gpx_out_file!=NULL)\r
+       {\r
+               if (pt_type == GPX_TRKPT)\r
+                       fprintf(gpx_out_file, "\t\t");\r
+               else if (pt_type == GPX_RTEPT)\r
+                       fprintf(gpx_out_file, "\t");\r
+               fprintf(gpx_out_file, "\t<%s lat=\"%f\" lon=\"%f\">%s</%s>\n",\r
+                               gpxptypelabel[pt_type], pt->lat, pt->lon,\r
+                               opt_elms, gpxptypelabel[pt_type]);\r
+       }\r
+}\r
+\r
+void gpx_write_jour_point(FILE* gpx_out_file, struct journey * jour, struct jour_rtept * wpt)\r
+{\r
+       struct gpxpt * pt = gpxpt_new();\r
+       char* opt_elms;\r
+       int optlen;\r
+       struct f_jour_pt_head * f_wpt_head;\r
+\r
+       if (gpx_out_file==NULL)\r
+               return;\r
+\r
+       // FIXME should compare the ppin and wpt coords if both exist\r
+       if (wpt->pushpin == NULL)\r
+       {\r
+               f_wpt_head = (struct f_jour_pt_head *)(jour->buf + (wpt->pthead_os));\r
+               pt->lat=scaled2deg(f_wpt_head->scaled_lat);\r
+               pt->lon=scaled2deg(f_wpt_head->scaled_lon);\r
+               optlen = f_wpt_head->cbtext1 + 60;\r
+               opt_elms = (char*)xmalloc(optlen);\r
+               //FIXME use str2ascii??\r
+               sprintf(opt_elms, "<name><![CDATA[%s]]></name>", wpt->text1);\r
+\r
+       }\r
+       else\r
+       {\r
+               optlen = strlen(wpt->pushpin->UdName) + strlen(wpt->pushpin->NoteShort) + 60;\r
+               opt_elms = (char*)xmalloc(optlen);\r
+\r
+               sprintf(opt_elms, "<name><![CDATA[%s]]></name><desc><![CDATA[%s]]></desc>",\r
+                               wpt->pushpin->UdName, wpt->pushpin->NoteShort);\r
+\r
+               pt->lat = wpt->pushpin->lat;\r
+               pt->lon = wpt->pushpin->lon;\r
+       }\r
+\r
+       gpx_write_point(gpx_out_file, pt, GPX_RTEPT, opt_elms);\r
+\r
+       gpxpt_delete(pt);\r
+       xfree(opt_elms);\r
+}\r
+\r
+void gpx_write_jour_header(FILE* gpx_out_file)\r
+{\r
+       if(gpx_out_file!=NULL)\r
+       {\r
+               fprintf(gpx_out_file, "\t<rte>\n");\r
+               fprintf(gpx_out_file, "\t\t<name>Journey</name>\n");\r
+               fprintf(gpx_out_file, "\t\t<src>Extracted from main Journey</src>\n");\r
+       }\r
+}\r
+\r
+void gpx_write_jour_trailer(FILE* gpx_out_file)\r
+{\r
+       if(gpx_out_file!=NULL)\r
+               fprintf(gpx_out_file, "\t</rte>\n");\r
+\r
+}\r
+\r
+void gpx_write_journey(FILE* gpx_out_file, struct journey * jour)\r
+{\r
+       int j;\r
+       if( (gpx_out_file!=NULL) && (jour!=NULL) && (jour->count_rtepts>0) )\r
+       {\r
+               printf("Writing gpx route for Journey\n");\r
+               gpx_write_jour_header(gpx_out_file);\r
+               for(j=0; j< jour->count_rtepts; j++)\r
+                       gpx_write_jour_point(gpx_out_file, jour, jour->rtept_list+j);\r
+               gpx_write_jour_trailer(gpx_out_file);\r
+       }\r
+}\r
+\r
+void gpx_write_pushpinlist (FILE* gpx_out_file, struct pushpin_safelist *ppplist)\r
+{\r
+       int i;\r
+       struct gpxpt * pt=NULL;\r
+       char* opt_elms;\r
+       int optlen;\r
+\r
+       if ((gpx_out_file==NULL) || (ppplist==NULL))\r
+               return;\r
+\r
+       pt = gpxpt_new();\r
+\r
+       printf("writting gpx waypoints for %d pushpins\n", ppplist->num_pushpins);\r
+\r
+       for (i=0; i<ppplist->num_pushpins; i++)\r
+       {\r
+               if (ppplist->pushpin_list[i]==NULL)\r
+                       break;\r
+\r
+               optlen = strlen(ppplist->pushpin_list[i]->UdName) \r
+                               + strlen(ppplist->pushpin_list[i]->NoteShort) + 60;\r
+               opt_elms = (char*)xmalloc(optlen);\r
+\r
+               sprintf(opt_elms, "<name><![CDATA[%s]]></name><desc><![CDATA[%s]]></desc>",\r
+                               ppplist->pushpin_list[i]->UdName, ppplist->pushpin_list[i]->NoteShort);\r
+\r
+               pt->lat = ppplist->pushpin_list[i]->lat;\r
+               pt->lon = ppplist->pushpin_list[i]->lon;\r
+\r
+               gpx_write_point(gpx_out_file, pt, GPX_WPT, opt_elms);\r
+               xfree(opt_elms);\r
+       }\r
+       fprintf(gpx_out_file, "\n");\r
+       gpxpt_delete(pt);\r
+}\r
+\r
+void gpx_write_annot_rec(FILE* gpx_out_file, const struct annot_rec * rec)\r
+{\r
+       int pt_type;\r
+       int p;\r
+       char opt_elms[200];\r
+       struct gpxpt * pt;\r
+\r
+       if ( (gpx_out_file==NULL) || (rec==NULL) )\r
+       {\r
+               return;\r
+       }\r
+\r
+       pt_type = GPX_TRKPT ;\r
+       if (opts.use_gpx_route)\r
+               pt_type = GPX_RTEPT;\r
+       switch (rec->type)\r
+       {\r
+       case ANNOT_TYPE_LINE:\r
+               // FIXME lots of format and name info to be added here\r
+\r
+\r
+               // *******************\r
+               //  rte or trk header\r
+               // *******************\r
+\r
+               if(opts.use_gpx_route)\r
+               {\r
+                       fprintf(gpx_out_file, "\t<rte>\n");\r
+                       fprintf(gpx_out_file, "\t\t<src>Extracted from Annotation %d (%s)</src>\n",\r
+                                       rec->annot_num, annot_type_name[rec->type]);\r
+                       fprintf(gpx_out_file, "\t\t<name>RT%04d</name>\n", rec->annot_num);\r
+               }\r
+               else\r
+               {\r
+                       fprintf(gpx_out_file, "\t<trk>\n");\r
+                       fprintf(gpx_out_file, "\t\t<name>TK%04d</name>\n", rec->annot_num);\r
+                       fprintf(gpx_out_file, "\t\t<src>Extracted from Annotation %d (%s)</src>\n",\r
+                                       rec->annot_num, annot_type_name[rec->type]);\r
+                       fprintf(gpx_out_file, "\t\t<trkseg>\n");\r
+               }\r
+\r
+               // *******************\r
+               //  rte or trk points\r
+               // *******************\r
+\r
+\r
+               for (p=0; p < rec->line_points; p++)\r
+               {\r
+                       pt=gpx_get_point(rec->buf + rec->line_offset + 12*p);\r
+                       if(pt==NULL)\r
+                       {\r
+                               printf("got null pt #%p in annotation %d, skipping more points in this annotation\n",\r
+                                               p, rec->annot_num);\r
+                               break;\r
+                       }\r
+                       if(opts.use_gpx_route)\r
+                               sprintf(opt_elms, "<name>rp%04d</name>", p);\r
+                       else\r
+                               // we need to include a name for trackpoints\r
+                               // for them to be recognised by easygps.\r
+                               sprintf(opt_elms, "<name>tp%04d</name>", p);\r
+                       gpx_write_point(gpx_out_file, pt, pt_type, opt_elms);\r
+                       gpxpt_delete(pt);\r
+               }\r
+\r
+               // ********************\r
+               //  rte or trk trailer\r
+               // ********************\r
+\r
+               if(opts.use_gpx_route)\r
+                       fprintf(gpx_out_file, "\t</rte>\n");\r
+               else\r
+                       fprintf(gpx_out_file, "\t\t</trkseg>\n\t</trk>\n");\r
+\r
+       case ANNOT_TYPE_OVAL:\r
+       case ANNOT_TYPE_TEXT:\r
+       case ANNOT_TYPE_CIRCLE:\r
+       default:\r
+               break;\r
+       }\r
+}\r
+\r
+void gpx_write_annotations(FILE* gpx_out_file, struct annotations * annots)\r
+{\r
+       int i;\r
+       if ( (gpx_out_file!=NULL) && (annots!=NULL) )\r
+               for (i=0; i < annots->num_annotations; i++)\r
+               {\r
+                       gpx_write_annot_rec(gpx_out_file, annots->annot_list[i]);\r
+               }\r
+}\r
+\r
+void gpx_write_all(char* gpx_out_file_name, \r
+                                  struct pushpin_safelist *ppplist, \r
+                                  struct journey * jour,\r
+                                  struct annotations * annots)\r
+{\r
+       FILE* gpx_out_file;\r
+       if ( (ppplist==NULL) && (jour==NULL) && (annots==NULL) )\r
+               return;\r
+       gpx_out_file = gpx_open_write_file_header(gpx_out_file_name);\r
+       gpx_write_pushpinlist(gpx_out_file, ppplist);\r
+       gpx_write_journey(gpx_out_file, jour);\r
+       gpx_write_annotations(gpx_out_file, annots);\r
+       gpx_write_file_trailer(gpx_out_file);\r
+}\r
+\r
diff --git a/st2gpx/src/writepcx.c b/st2gpx/src/writepcx.c
new file mode 100644 (file)
index 0000000..16d2935
--- /dev/null
@@ -0,0 +1,469 @@
+/*\r
+       writepcx.c\r
+\r
+       Extract data from MS Streets & Trips .est and Autoroute .axe files in GPX format.\r
+\r
+    Copyright (C) 2003 James Sherring, james_sherring@yahoo.com\r
+\r
+    This program is free software; you can redistribute it and/or modify\r
+    it under the terms of the GNU General Public License as published by\r
+    the Free Software Foundation; either version 2 of the License, or\r
+    (at your option) any later version.\r
+\r
+    This program is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+\r
+    You should have received a copy of the GNU General Public License\r
+    along with this program; if not, write to the Free Software\r
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA\r
+\r
+\r
+       This app depends on istorage & istorage-make from Pabs (pabs3@zip.to)\r
+       and James Clark's Expat xml parser from http://www.libexpat.org/.\r
+\r
+*/\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <math.h>\r
+#include <memory.h>\r
+#include <string.h>\r
+\r
+#include "gpx.h"\r
+#include "st2gpx.h"\r
+#include "ppinutil.h"\r
+#include "journey.h"\r
+#include "annotations.h"\r
+\r
+#define GAR_WPT_HEADER "H  IDNT   LATITUDE    LONGITUDE    DATE      TIME     ALT   DESCRIPTION                              PROXIMITY     SYMBOL ;waypts\n"\r
+#define GAR_RTE_HEADER_JOUR "R 01  Streets&Trips Journey\n"\r
+#define GAR_TRK_HEADER "H  LATITUDE    LONGITUDE    DATE      TIME     ALT    ;track\n"\r
+\r
+#define GAR_WPT 1\r
+#define GAR_RTE 2\r
+#define GAR_TRK 3\r
+\r
+// maximum number of susbstitutions to try get a unique IDENT\r
+#define MAX_IDENT_SUB 10000\r
+\r
+char* strpad(char* str, int padlen)\r
+// Right-pad a string with spaces so that strlen(str)=padlen,\r
+// or just truncate str if it is longer that padlen.\r
+// str must have at least padlen+1 bytes allocated.\r
+{\r
+       int i;\r
+       str[padlen]=0;\r
+       for(i=strlen(str); i<padlen; i++)\r
+               str[i]=' ';\r
+       str[padlen]=0;\r
+       //printf("strpad, got:%s\n",str);\r
+       return str;\r
+}\r
+\r
+// WPT names (IDENT) need to be 6 characters, uppercase,\r
+// and in [A-Z,0-9,-, ]. I.e. asc 48-57, 65-90, 45, 58\r
+void garmin_ident_crush(char* str)\r
+{\r
+       int i;\r
+       char c;\r
+       strpad(str, 6);\r
+       //convert to upper - cant I just do a (portable) subtraction or something?\r
+       //_strupr(str);\r
+       for(i=0; i<6; i++)\r
+       {\r
+               c=str[i];\r
+               //convert to upper\r
+               // FIXME - cant I do something for accented letters?\r
+               if ((c>96) && (c<123))\r
+                       c= str[i]=c-32;\r
+               //convert all non-conforming characters to spaces\r
+               if( !( ((c>47) && (c<59)) || ((c>64) && (c<91)) || (c==45) ))\r
+               {\r
+                       str[i]=' ';\r
+               }\r
+       }\r
+       str[6]=0;\r
+}\r
+\r
+void comp_mk_uniq_idents(char* ident_array, int ident_to_mk_uniq, int count_idents) \r
+// compare ident_to_mk_uniq-th ident to all preceding idents,\r
+// and make ident_to_mk_uniq-th ident\r
+{\r
+       int j;\r
+       int k;\r
+       int m;\r
+       char test_ident[7];\r
+       char uniq_part[7];\r
+       int duplicate_flag;\r
+\r
+       // compare this ident with all the idents verified as unique\r
+       for(j=0; j<ident_to_mk_uniq; j++)\r
+               if (strcmp(ident_array+7*ident_to_mk_uniq, ident_array+7*j)==0)\r
+               {\r
+                       //try to make a new ident, by setting the end to Xk, try k up to 5 digits\r
+                       strncpy(test_ident, ident_array+7*ident_to_mk_uniq, 7);\r
+                       for (k=0; k<MAX_IDENT_SUB; k++)\r
+                       {\r
+                               sprintf(uniq_part, "X%d", k);\r
+                               strcpy(test_ident+6-strlen(uniq_part), uniq_part);\r
+                               if (strlen(test_ident) != 6)\r
+                               {\r
+                                       fprintf(stderr, "Oops, I got my calcs wrong in making unique IDENT, got '%s'\n", test_ident);\r
+                                       debug_pause();\r
+                                       exit(1);\r
+                               }\r
+                               duplicate_flag=0;\r
+                               // compare the test_ident to *all* other  idents,\r
+                               // so that we dont create a later duplicate\r
+                               for (m=0; m<count_idents; m++)\r
+                                       if ( (m!=ident_to_mk_uniq) && (strcmp(test_ident, ident_array+7*m)==0) )\r
+                                       {\r
+                                               duplicate_flag=1;\r
+                                               break;\r
+                                       }\r
+                               if (duplicate_flag==0)\r
+                                       break;\r
+                       }\r
+                       if (k==MAX_IDENT_SUB)\r
+                               printf("Panick! **** How could there be %d duplicate IDENTs ?!?\n", MAX_IDENT_SUB);\r
+\r
+                       printf("Got duplicate Garmin IDENT '%s' for pushpin(%d) and pushpin(%d), so for pushpin(%d) I'm using '%s'\n",\r
+                               ident_array+7*j, ident_to_mk_uniq, j, ident_to_mk_uniq, test_ident);\r
+\r
+                       // ?????\r
+                       strncpy(ident_array + 7*ident_to_mk_uniq, test_ident, 7);\r
+               }\r
+}\r
+\r
+void make_uniq_idents(struct pushpin_safelist * ppplist, struct journey * jour)\r
+{\r
+       int i;\r
+       int j;\r
+       struct f_jour_pt_head * f_wpt_head=NULL;\r
+       float lat;\r
+       float lon;\r
+       int count_ppins;\r
+\r
+       // this is an array of n*6 bytes\r
+       char *ident_array;\r
+\r
+       if (jour==NULL)\r
+       {\r
+               printf("Unexpected jour=NULL in make_uniq_idents.\n");\r
+               return;\r
+       }\r
+       if (ppplist==NULL)\r
+       {\r
+               count_ppins=0;\r
+               if(jour->count_rtepts == 0)\r
+                       return;\r
+       }\r
+       else\r
+               count_ppins=ppplist->num_pushpins;\r
+       \r
+       ident_array=(char*)xmalloc(7*(count_ppins + jour->count_rtepts));\r
+\r
+       // copy ppin names before we start mangling them\r
+       for (i=0; i< (count_ppins); i++)\r
+       {\r
+               if(ppplist->pushpin_list[i]->UdName)\r
+                       memcpy(ident_array +7*i, ppplist->pushpin_list[i]->UdName, 6);\r
+               else\r
+                       ident_array[7*i]=0;\r
+               //printf("pushpin_list[%d]->UdName:%s\n", i, ppplist->pushpin_list[i]->UdName);\r
+               //printf("ident_array[7*%d]:%s\n", i, ident_array+7*i);\r
+               garmin_ident_crush(ident_array+7*i);\r
+               //printf("Made Ident:%s\n",ident_array+7*i );\r
+       }\r
+\r
+       // copy rtept names before we start mangling them\r
+       for (i=0; i< (jour->count_rtepts); i++)\r
+       {\r
+               memcpy(ident_array + 7*(count_ppins) +7*i, \r
+                          jour->rtept_list[i].text1, \r
+                          6);\r
+               garmin_ident_crush(ident_array + 7*(count_ppins) + 7*i);\r
+       }\r
+\r
+       // compare all fresh ppin idents\r
+       for(i=0; i<(count_ppins); i++)\r
+       {\r
+               // Verify ident_array[7*i] is unique.\r
+               // Create a unique ident if neccesary.\r
+               // Only check against list of already-verified unique\r
+               comp_mk_uniq_idents(ident_array, i, count_ppins + jour->count_rtepts);\r
+               \r
+               strncpy(ppplist->pushpin_list[i]->garmin_ident, ident_array+7*i, 7);\r
+       }\r
+\r
+       // compare jour rtept idents to ppin idents + other jour rtept idents\r
+       for(i=0; i<jour->count_rtepts; i++)\r
+       {\r
+               if (jour->rtept_list[i].pushpin != NULL)\r
+               {\r
+                       // The rtept has a matching pushpin, so use the pushpin's garmin_ident\r
+                       memcpy(jour->rtept_list[i].garmin_ident,\r
+                                  jour->rtept_list[i].pushpin->garmin_ident,\r
+                                  7);\r
+               }\r
+               else\r
+               {\r
+                       f_wpt_head = (struct f_jour_pt_head *)(jour->buf + (jour->rtept_list[i].pthead_os));\r
+                       lat=scaled2deg(f_wpt_head->scaled_lat);\r
+                       lon=scaled2deg(f_wpt_head->scaled_lon);\r
+                       for(j=0; j<count_ppins; j++)\r
+                               // Is this ppin closer than 0.00001 deg?\r
+                               // This wont work for -180, 180, but thats not realistic or a problem\r
+                               // It is questionable if this is even desirable when the ppin name is different,\r
+                               // perhaps we want the different name also?\r
+                               if( (fabs(lat-ppplist->pushpin_list[j]->lat)<0.00001)\r
+                                   && (fabs(lon-ppplist->pushpin_list[j]->lon)<0.00001) )\r
+                               {\r
+                                       // The rtept has a matching pushpin, so use the pushpin's garmin_ident\r
+                                       memcpy(ident_array + 7*(count_ppins) +7*i,\r
+                                                  ppplist->pushpin_list[j]->garmin_ident,\r
+                                                  7);\r
+                                       // Although the journey stream doesn't associate this pushpin with the route,\r
+                                       // I have decided to. Again, this is questionable \r
+                                       // but not likely to happen anyway.\r
+                                       jour->rtept_list[i].pushpin = ppplist->pushpin_list[j];\r
+                               }\r
+                               else\r
+                               {\r
+                                       // no matching wpt for this rtept, so we need to create one.\r
+                                       // We just create the garmin_ident in the jour-rtept here, \r
+                                       // later we will write a corresponding wpt to the pcx file.\r
+                                       comp_mk_uniq_idents(ident_array, count_ppins + i, count_ppins + jour->count_rtepts);\r
+                               }                               \r
+               }\r
+               // set the jour-rtept garmin_ident\r
+               memcpy(jour->rtept_list[i].garmin_ident,\r
+                          ident_array + 7*(count_ppins) +7*i,\r
+                          7);\r
+       }\r
+       xfree(ident_array);\r
+}\r
+\r
+void gar_write_header(FILE* gar_out_file)\r
+{\r
+       fprintf(gar_out_file, "H  SOFTWARE NAME & VERSION\n");\r
+       fprintf(gar_out_file, "I  PCX5 2.09 output from st2gpx by James Sherring - james_sherring@yahoo.com");\r
+       fprintf(gar_out_file, "\n");\r
+       fprintf(gar_out_file, "H  R DATUM                IDX DA            DF            DX            DY            DZ\n");\r
+       fprintf(gar_out_file, "M  G WGS 84               121 +0.000000e+00 +0.000000e+00 +0.000000e+00 +0.000000e+00 +0.000000e+00\n");\r
+       fprintf(gar_out_file, "\n");\r
+       fprintf(gar_out_file, "H  COORDINATE SYSTEM\n");\r
+       fprintf(gar_out_file, "U  LAT LON DM\n");\r
+       fprintf(gar_out_file, "\n");\r
+}\r
+\r
+void pcx5_write_pt(FILE* file, int pt_type, char ident[7], double lat, double lon, char timedate[19],\r
+                                  float alt, char desc[41], float proximity,   int symbol)\r
+{\r
+       //char outbuf[118];\r
+       char lat_sym;\r
+       char lon_sym;\r
+       int lat_deg;\r
+       int lon_deg;\r
+       double lat_min;\r
+       double lon_min;\r
+\r
+       if (lat<0)\r
+               lat_sym='S';\r
+       else\r
+               lat_sym='N';\r
+\r
+       if (lon<0)\r
+               lon_sym='W';\r
+       else\r
+               lon_sym='E';\r
+\r
+       lat_deg=(int)floor(fabs(lat));\r
+       lon_deg=(int)floor(fabs(lon));\r
+\r
+       lat_min=(fabs(lat)-lat_deg)*60;\r
+       lon_min=(fabs(lon)-lon_deg)*60;\r
+\r
+       if ( (pt_type == GAR_WPT) || (pt_type == GAR_RTE) )\r
+               fprintf(file, "W  %6.6s ", ident);\r
+       else if (pt_type == GAR_TRK)\r
+               fprintf(file, "T  ");\r
+\r
+       fprintf(file, "%c%02.2d%08.5f %c%03.3d%08.5f", lat_sym, lat_deg, lat_min, lon_sym, lon_deg, lon_min);\r
+       fprintf(file, " %18.18s %5.5s", timedate, "    ");\r
+\r
+       if ( (pt_type == GAR_WPT) || (pt_type == GAR_RTE) )\r
+               fprintf(file, " %40.40s %13.13s %1.3d \n", desc, "              ", symbol);\r
+       else if (pt_type == GAR_TRK)\r
+               fprintf(file, "\n");\r
+\r
+}\r
+\r
+void pcx5_write_ppin(FILE* file, struct pushpin * ppin)\r
+{\r
+       char timedate[19]="";\r
+       float alt=0;\r
+       char desc[41]="";\r
+       float proximity=0;\r
+       // FIXME this should come from the pushpin icon\r
+       int symbol=8; // or 18\r
+\r
+       strpad(timedate, 19);\r
+\r
+       // Should I create a meaningful note if there is none?\r
+       if(ppin->NoteShort)\r
+               memcpy(desc, ppin->NoteShort, 40);\r
+       else\r
+               desc[0]=0;\r
+       strpad(desc, 40);\r
+\r
+       pcx5_write_pt(file, GAR_WPT, ppin->garmin_ident, ppin->lat, ppin->lon, timedate,\r
+               alt, desc, proximity, symbol);\r
+}\r
+\r
+void pcx5_write_ppin_list(FILE* file, struct pushpin_safelist * ppplist)\r
+{\r
+       int i;\r
+\r
+       if ( (file==NULL) || (ppplist==NULL))\r
+               return;\r
+\r
+       fprintf(file, GAR_WPT_HEADER);\r
+       for (i=0; i< (ppplist->num_pushpins); i++)\r
+               pcx5_write_ppin(file, ppplist->pushpin_list[i]);\r
+}\r
+\r
+void pcx5_write_jour_pt(FILE* file, struct journey * jour, struct jour_rtept * rtept, int pt_type)\r
+{\r
+       char timedate[19]="";\r
+       float alt=0;\r
+       char desc[40];\r
+       float proximity=0;\r
+\r
+       int symbol=8; // or 18\r
+       struct f_jour_pt_head * f_wpt_head;\r
+\r
+//     if(pt_type==GAR_WPT)\r
+//     {\r
+               f_wpt_head = (struct f_jour_pt_head *)(jour->buf + (rtept->pthead_os));\r
+\r
+               strpad(timedate, 19);\r
+\r
+               strcpy(desc, rtept->text1);\r
+               strpad(desc, 40);\r
+\r
+               pcx5_write_pt(file, \r
+                                         pt_type, \r
+                                         rtept->garmin_ident, \r
+                                         scaled2deg(f_wpt_head->scaled_lat), \r
+                                         scaled2deg(f_wpt_head->scaled_lon), \r
+                                         timedate,     \r
+                                         alt, \r
+                                         desc, \r
+                                         proximity, \r
+                                         symbol);\r
+//     }\r
+//     else if(pt_type==GAR_RTE)\r
+//     {\r
+//             // this is easier that calling pcx5_write_pt\r
+//             fprintf(file, "W  %6.6s \n", rtept->garmin_ident);\r
+//     }\r
+}\r
+\r
+void pcx5_write_journey(FILE* file, struct journey * jour, struct pushpin_safelist * ppplist)\r
+{\r
+       int i;\r
+\r
+       if( (jour==NULL) || ((jour->count_rtepts) < 1) )\r
+               return;\r
+\r
+       // write jour rte-pts w/o ppin as wpts\r
+//     for(i=0; i< jour->count_rtepts; i++)\r
+//             if(jour->rtept_list[i].pushpin == NULL)\r
+//                     pcx5_write_jour_pt(file, jour, jour->rtept_list + i, GAR_WPT);\r
+\r
+       fprintf(file, "\n");\r
+       fprintf(file, GAR_RTE_HEADER_JOUR);\r
+       fprintf(file, "\n");\r
+       fprintf(file, GAR_WPT_HEADER);\r
+\r
+       for(i=0; i< jour->count_rtepts; i++)\r
+               if(jour->rtept_list[i].pushpin)\r
+                       pcx5_write_ppin(file, jour->rtept_list[i].pushpin);\r
+               else\r
+                       pcx5_write_jour_pt(file, jour, jour->rtept_list+i, GAR_RTE);\r
+}\r
+\r
+void pcx5_write_annot_line(FILE* file, struct annot_rec * pannot)\r
+{\r
+       int p;\r
+       char timedate[19]="";\r
+       float alt=0;\r
+       struct gpxpt * pt;\r
+\r
+       if (pannot==NULL)\r
+               return;\r
+\r
+       fprintf(file, "\n");\r
+       fprintf(file, GAR_TRK_HEADER);\r
+\r
+       strpad(timedate, 19);\r
+\r
+       for(p=0; p<pannot->line_points; p++)\r
+       {\r
+               pt=gpx_get_point(pannot->buf + pannot->line_offset + 12*p);\r
+               if (pt != NULL)\r
+                       pcx5_write_pt(file, GAR_TRK, "", pt->lat, pt->lon, timedate,\r
+                                                 alt, "", 0, 0);\r
+               else\r
+               {\r
+                       printf("Null gpx_pt #%p from annotation %d, skipping more points in this annotation\n",\r
+                                   pannot->annot_num);\r
+                       break;\r
+               }\r
+               gpxpt_delete(pt);\r
+       }\r
+}\r
+\r
+void pcx5_write_annots(FILE* file, struct annotations * pannots)\r
+{\r
+       int i;\r
+       if (pannots==NULL)\r
+               return;\r
+\r
+       for(i=0; i < pannots->num_annotations; i++)\r
+               if ( (pannots->annot_list[i]->type) == ANNOT_TYPE_LINE)\r
+                       pcx5_write_annot_line(file, pannots->annot_list[i]);\r
+\r
+}\r
+\r
+void pcx5_export(char* pcx5_out_file_name, struct pushpin_safelist * ppplist, struct journey * jour, struct annotations * pannots)\r
+{\r
+       FILE* pcx5_out_file=NULL;\r
+       struct pushpin_safelist * new_ppplist=NULL;\r
+\r
+       if ( (ppplist==NULL) && (jour==NULL) && (pannots==NULL) )\r
+               return;\r
+\r
+       // Because Garmin can only accept a nasty 6 char alphanumeric unique ID\r
+       make_uniq_idents(ppplist, jour);\r
+\r
+       if (pcx5_out_file_name)\r
+       {\r
+               pcx5_out_file = fopen(pcx5_out_file_name, "w");\r
+               if (pcx5_out_file == NULL)\r
+               {\r
+                       fprintf(stderr, "Cannot open %s\n", pcx5_out_file_name);\r
+                       debug_pause();\r
+                       exit(1);\r
+               }\r
+       }\r
+       else\r
+               return;\r
+\r
+       gar_write_header(pcx5_out_file);\r
+       pcx5_write_ppin_list(pcx5_out_file, ppplist);\r
+       pcx5_write_journey(pcx5_out_file, jour, ppplist);\r
+       pcx5_write_annots(pcx5_out_file, pannots);\r
+};\r